<!DOCTYPE html>
<html lang="en">

<!-- Head tag -->
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="google-site-verification" content="xBT4GhYoi5qRD5tr338pgPM5OWHHIDR6mNg1a3euekI" />
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="keyword"  content="">
    <link rel="shortcut icon" href="/img/logo.png">
    <!-- Place this tag in your head or just before your close body tag. -->
    <script async defer src="https://buttons.github.io/buttons.js"></script>
    <title>
        
          leetcode解题报告 - 宋正兵的博客 | zbsong Blog
        
    </title>

    <link rel="canonical" href="zbsong.top/article/leetcode解题报告/">

    <!-- Bootstrap Core CSS -->
    <link rel="stylesheet" href="/css/bootstrap.min.css">

    <!-- Custom CSS --> 
    <link rel="stylesheet" href="/css/beantech.min.css">

    <link rel="stylesheet" href="/css/donate.css">
    
    <!-- Pygments Highlight CSS -->
    <link rel="stylesheet" href="/css/highlight.css">

    <link rel="stylesheet" href="/css/widget.css">

    <link rel="stylesheet" href="/css/rocket.css">

    <link rel="stylesheet" href="/css/signature.css">

    <link rel="stylesheet" href="/css/toc.css">

    <!-- Custom Fonts -->
    <!-- <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet" type="text/css"> -->
    <!-- Hux change font-awesome CDN to qiniu -->
    <link href="https://cdn.staticfile.org/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" type="text/css">


    <!-- Hux Delete, sad but pending in China
    <link href='http://fonts.googleapis.com/css?family=Lora:400,700,400italic,700italic' rel='stylesheet' type='text/css'>
    <link href='http://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800' rel='stylesheet' type='text/
    css'>
    -->


    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
        <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
        <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->

    <!-- ga & ba script hoook -->
    <script></script>
</head>


<!-- hack iOS CSS :active style -->
<body ontouchstart="">
	<!-- Modified by Yu-Hsuan Yen -->
<!-- Post Header -->
<style type="text/css">
    header.intro-header{
        
            background-image: url('https://api.dujin.org/bing/1920.php')
            /*post*/
        
    }
    
</style>

<header class="intro-header" >
    <!-- Signature -->
    <div id="signature">
        <div class="container">
            <div class="row">
                <div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
                
                    <div class="post-heading">
                        <div class="tags">
                            
                              <a class="tag" href="/tags/#algorithm" title="algorithm">algorithm</a>
                            
                        </div>
                        <h1>leetcode解题报告</h1>
                        <!-- <h2 class="subheading">记录了在leetcode刷题的答案</h2> -->
                        <span class="meta">
                            宋正兵 更新 on
                            2021-04-14
                        </span>
                    </div>
                


                </div>
            </div>
        </div>
    </div>
</header>

    <!-- Navigation -->
<nav class="navbar navbar-default navbar-custom navbar-fixed-top">
    <div class="container-fluid">
        <!-- Brand and toggle get grouped for better mobile display -->
        <div class="navbar-header page-scroll">
            <button type="button" class="navbar-toggle">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="/">songzblink</a>
        </div>

        <!-- Collect the nav links, forms, and other content for toggling -->
        <!-- Known Issue, found by Hux:
            <nav>'s height woule be hold on by its content.
            so, when navbar scale out, the <nav> will cover tags.
            also mask any touch event of tags, unfortunately.
        -->
        <div id="huxblog_navbar">
            <div class="navbar-collapse">
                <ul class="nav navbar-nav navbar-right">
                    <li>
                        <a href="/">主页</a>
                    </li>
					<li>
                        <a href="/archive/">归档</a>
                    </li>
					<li>
                        <a href="/tags/">标签</a>
                    </li>
					<li>
                        <a href="/about/">关于</a>
                    </li>
					<!--
					修改about在前面的问题
                    
                        
                    
                        
                        <li>
                            <a href="/about/">关于</a>
                        </li>
                        
                    
                        
                        <li>
                            <a href="/archive/">归档</a>
                        </li>
                        
                    
                        
                        <li>
                            <a href="/tags/">标签</a>
                        </li>
                        
                    
                    -->
                </ul>
            </div>
        </div>
        <!-- /.navbar-collapse -->
    </div>
    <!-- /.container -->
</nav>
<script>
    // Drop Bootstarp low-performance Navbar
    // Use customize navbar with high-quality material design animation
    // in high-perf jank-free CSS3 implementation
    var $body   = document.body;
	// querySelector 获取文档中 id="demo" 的元素
    var $toggle = document.querySelector('.navbar-toggle');
    var $navbar = document.querySelector('#huxblog_navbar');
    var $collapse = document.querySelector('.navbar-collapse');

    $toggle.addEventListener('click', handleMagic)
    function handleMagic(e){
        if ($navbar.className.indexOf('in') > 0) {
        // CLOSE
            $navbar.className = " ";
            // wait until animation end.
            setTimeout(function(){
                // prevent frequently toggle
                if($navbar.className.indexOf('in') < 0) {
                    $collapse.style.height = "0px"
                }
            },400)
        }else{
        // OPEN
            $collapse.style.height = "auto"
            $navbar.className += " in";
        }
    }
</script>


    <!-- Main Content -->
    <!-- Modify by Yu-Hsuan Yen -->

<!-- Post Content -->
<article>
    <div class="container">
        <div class="row">

            <!-- Post Container -->
            <div class="
                col-lg-8 col-lg-offset-2
                col-md-10 col-md-offset-1
                post-container">

				
                <blockquote>
<p><font id="qusnum"></font></p>
<script src="/js/jquery.min.js"></script>
<script language="javascript" type="text/javascript">
$(document).ready(function(){
    var i=$('h2').size();
    var years = {};
 var myDate = new Date(); 
 var year = myDate.getFullYear();
 var month = myDate.getMonth()+1;
 var day = myDate.getDate();
 var newDay = year + "年" + month + "月" + day + "日";
    var str = '截至' + newDay +  '，已收录' + i + '道题目。';
    document.getElementById('qusnum').innerHTML = str;
});
</script>
</blockquote>
<h1 id="1-二叉树专题">1、二叉树专题</h1>
<h2 id="总结">总结</h2>
<ul>
<li>掌握二叉树递归与非递归遍历</li>
</ul>
<h2 id="模板">模板</h2>
<p>模板整理来源</p>
<p>作者：gre-z<br>
链接：<a href="https://leetcode-cn.com/problems/binary-tree-postorder-traversal/solution/leetcodesuan-fa-xiu-lian-dong-hua-yan-shi-xbian--2/" target="_blank" rel="noopener">https://leetcode-cn.com/problems/binary-tree-postorder-traversal/solution/leetcodesuan-fa-xiu-lian-dong-hua-yan-shi-xbian–2/</a><br>
来源：力扣（LeetCode）<br>
著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。</p>
<h3 id="前序遍历模板递归">前序遍历模板（递归）</h3>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">preOrderRecur</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (root == <span class="keyword">null</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    System.out.print(root.value + <span class="string">" "</span>);</span><br><span class="line">    preOrderRecur(root.left);</span><br><span class="line">    preOrderRecur(root.right);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="前序遍历模板迭代">前序遍历模板（迭代）</h3>
<p>首先我们应该创建一个 <code>Stack</code> 用来存放节点，首先我们想要打印根节点的数据，此时 <code>Stack</code> 里面的内容为空，所以我们优先将头结点加入 <code>Stack</code> ，然后打印。</p>
<p>之后我们应该先打印左子树，然后右子树。所以先加入<code>Stack</code> 的就是右子树，然后左子树。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">preOrderIteration</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">	<span class="keyword">if</span> (root == <span class="keyword">null</span>) &#123;</span><br><span class="line">		<span class="keyword">return</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	Stack&lt;TreeNode&gt; stack = <span class="keyword">new</span> Stack&lt;&gt;();</span><br><span class="line">	stack.push(root);</span><br><span class="line">	<span class="keyword">while</span> (!stack.isEmpty()) &#123;</span><br><span class="line">		TreeNode tempNode = stack.pop();</span><br><span class="line">		System.out.print(tempNode.value + <span class="string">" "</span>);</span><br><span class="line">		<span class="keyword">if</span> (tempNode.right != <span class="keyword">null</span>) &#123;</span><br><span class="line">			stack.push(tempNode.right);</span><br><span class="line">		&#125;</span><br><span class="line">		<span class="keyword">if</span> (tempNode.left != <span class="keyword">null</span>) &#123;</span><br><span class="line">			stack.push(tempNode.left);</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="中序遍历模板递归">中序遍历模板（递归）</h3>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">preOrderRecur</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (root == <span class="keyword">null</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    preOrderRecur(root.left);</span><br><span class="line">    System.out.print(root.value + <span class="string">" "</span>);</span><br><span class="line">    preOrderRecur(root.right);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="中序遍历模板迭代">中序遍历模板（迭代）</h3>
<ol>
<li>创建一个 <code>Stack</code> ，然后按 左 中 右的顺序输出节点。</li>
<li>尽可能的将这个节点的左子树压入 <code>Stack</code> ，此时栈顶的元素是最左侧的元素，其目的是找到一个最小单位的子树(也就是最左侧的一个节点)，并且在寻找的过程中记录了来源，才能返回上层，同时在返回上层的时候已经处理完毕左子树了。</li>
<li>当处理完最小单位的子树时，返回到上层处理了中间节点。（如果把整个左中右的遍历都理解成子树的话，就是处理完 左子树-&gt;中间(就是一个节点)-&gt;右子树）</li>
<li>如果有右节点，其也要进行中序遍历。</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">inOrderIteration</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">	<span class="keyword">if</span> (root == <span class="keyword">null</span>) &#123;</span><br><span class="line">		<span class="keyword">return</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	TreeNode tempNode = root;</span><br><span class="line">	Stack&lt;TreeNode&gt; stack = <span class="keyword">new</span> Stack&lt;&gt;();</span><br><span class="line">	<span class="keyword">while</span> (!stack.isEmpty() || tempNode != <span class="keyword">null</span>) &#123;</span><br><span class="line">		<span class="keyword">while</span> (tempNode != <span class="keyword">null</span>) &#123;</span><br><span class="line">			stack.push(tempNode);</span><br><span class="line">			tempNode = tempNode.left;</span><br><span class="line">		&#125;</span><br><span class="line">		tempNode = stack.pop();</span><br><span class="line">		System.out.print(tempNode.value + <span class="string">" "</span>);</span><br><span class="line">		tempNode = tempNode.right;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">栈S;</span><br><span class="line">p= root;</span><br><span class="line"><span class="keyword">while</span>(p || S不空)&#123;</span><br><span class="line">    <span class="keyword">while</span>(p)&#123;</span><br><span class="line">        p入S;</span><br><span class="line">        p = p的左子树;</span><br><span class="line">    &#125;</span><br><span class="line">    p = S.top 出栈;</span><br><span class="line">    访问p;</span><br><span class="line">    p = p的右子树;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="后续遍历模板递归">后续遍历模板（递归）</h3>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">postOrderRecur</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (root == <span class="keyword">null</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    postOrderRecur(root.left);</span><br><span class="line">    postOrderRecur(root.right);</span><br><span class="line">    System.out.print(root.value + <span class="string">" "</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="后续遍历模板1迭代">后续遍历模板1（迭代）</h3>
<ol>
<li>前序遍历的过程 是 中左右。</li>
<li>将其转化成 中右左。也就是压栈的过程中优先压入左子树，在压入右子树。</li>
<li>然后将这个结果返回来，这里是利用栈的先进后出倒序打印。</li>
</ol>
 <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">postOrderIteration</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (root == <span class="keyword">null</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    Stack&lt;TreeNode&gt; stack1 = <span class="keyword">new</span> Stack&lt;&gt;();</span><br><span class="line">    Stack&lt;TreeNode&gt; stack2 = <span class="keyword">new</span> Stack&lt;&gt;();</span><br><span class="line">    stack1.push(root);</span><br><span class="line">    <span class="keyword">while</span> (!stack1.isEmpty()) &#123;</span><br><span class="line">        TreeNode tempNode = stack1.pop();</span><br><span class="line">        stack2.push(tempNode);</span><br><span class="line">        <span class="keyword">if</span> (tempNode.left != <span class="keyword">null</span>) &#123;</span><br><span class="line">            stack1.push(tempNode.left);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (tempNode.right != <span class="keyword">null</span>) &#123;</span><br><span class="line">            stack1.push(tempNode.right);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">while</span> (!stack2.isEmpty()) &#123;</span><br><span class="line">        System.out.print(stack2.pop().value + <span class="string">" "</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="后续遍历模板2迭代">后续遍历模板2（迭代）</h3>
<ol>
<li>用一个指针 <code>cur</code> 标记当前退出的节点是什么。</li>
<li>后序遍历的过程中在遍历完左子树跟右子树 <code>cur</code> 都会回到根结点。所以当前不管是从左子树还是右子树回到根结点都不应该再操作了，应该退回上层。</li>
<li>如果是从右边再返回根结点，应该回到上层。</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">postOrderIteration2</span><span class="params">(TreeNode root)</span> </span>&#123; </span><br><span class="line">	<span class="keyword">if</span> (root == <span class="keyword">null</span>) &#123;</span><br><span class="line">		<span class="keyword">return</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	TreeNode cur = root;</span><br><span class="line">	Stack&lt;TreeNode&gt; stack = <span class="keyword">new</span> Stack&lt;&gt;();</span><br><span class="line">	stack.push(head);</span><br><span class="line">	<span class="keyword">while</span> (!stack.isEmpty()) &#123;</span><br><span class="line">		TreeNode peek = stack.peek();</span><br><span class="line">		<span class="keyword">if</span> (peek.left != <span class="keyword">null</span> &amp;&amp; peek.left != cur &amp;&amp; peek.right != cur) &#123;</span><br><span class="line">			stack.push(peek.left);</span><br><span class="line">		&#125; <span class="keyword">else</span> <span class="keyword">if</span> (peek.right != <span class="keyword">null</span> &amp;&amp; peek.right != cur) &#123;</span><br><span class="line">			stack.push(peek.right);</span><br><span class="line">		&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">			System.out.print(stack.pop().val + <span class="string">" "</span>);</span><br><span class="line">			cur = peek;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="层次遍历模板-bfs模板">层次遍历模板 BFS模板</h3>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">bfs</span><span class="params">(Node root)</span> </span>&#123;</span><br><span class="line">        Queue&lt;Node&gt; queue = <span class="keyword">new</span> LinkedList&lt;&gt;();</span><br><span class="line">        <span class="keyword">if</span> (root != <span class="keyword">null</span>) &#123;</span><br><span class="line">            queue.offer(root);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">while</span> (!queue.isEmpty()) &#123;</span><br><span class="line">            Node tempNode = queue.poll();</span><br><span class="line">            <span class="comment">// visit</span></span><br><span class="line">           	<span class="keyword">for</span>(遍历所有tempNode的相邻节点nextNode) &#123;</span><br><span class="line">                <span class="keyword">if</span> (nextNode节点有效 &amp;&amp; visited[nextNode]==<span class="number">0</span>) &#123;</span><br><span class="line">                    visited[nextNode] = <span class="number">1</span>;</span><br><span class="line">                    queue.offer(nextNode);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="层次遍历模板-bfs模板-可以确定遍历到哪一层">层次遍历模板 BFS模板 可以确定遍历到哪一层</h3>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">bfs</span><span class="params">(Node root)</span> </span>&#123;</span><br><span class="line">        Queue&lt;Node&gt; queue = <span class="keyword">new</span> LinkedList&lt;&gt;();</span><br><span class="line">        <span class="keyword">if</span> (root != <span class="keyword">null</span>) &#123;</span><br><span class="line">            queue.offer(root);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">int</span> level = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">while</span> (!queue.isEmpty()) &#123;</span><br><span class="line">            <span class="keyword">int</span> size = queue.size();</span><br><span class="line">            <span class="keyword">while</span> (size &gt; <span class="number">0</span>) &#123;</span><br><span class="line">                Node tempNode = queue.poll();</span><br><span class="line">                size--;</span><br><span class="line">                <span class="comment">// visit</span></span><br><span class="line">                <span class="keyword">for</span>(遍历所有tempNode的相邻节点nextNode) &#123;</span><br><span class="line">                    <span class="keyword">if</span> (nextNode节点有效 &amp;&amp; visited[nextNode]==<span class="number">0</span>) &#123;</span><br><span class="line">                        visited[nextNode] = <span class="number">1</span>;</span><br><span class="line">                        queue.offer(nextNode);</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            level++;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="144-二叉树的前序遍历">144. 二叉树的前序遍历</h2>
<p><a href="https://leetcode-cn.com/problems/binary-tree-preorder-traversal/" target="_blank" rel="noopener">二叉树的前序遍历</a></p>
<p><strong>递归</strong> 根左右</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">class Solution &#123;</span><br><span class="line">    List&lt;Integer&gt; list = new LinkedList&lt;Integer&gt;();</span><br><span class="line">    public List&lt;Integer&gt; preorderTraversal(TreeNode root) &#123;</span><br><span class="line">        preOrder(root);</span><br><span class="line">        return list;        </span><br><span class="line">    &#125;</span><br><span class="line">    public void preOrder(TreeNode root) &#123;</span><br><span class="line">        if (root == null) &#123;</span><br><span class="line">            return;</span><br><span class="line">        &#125;</span><br><span class="line">        list.add(root.val);</span><br><span class="line">        preorderTraversal(root.left);</span><br><span class="line">        preorderTraversal(root.right);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>迭代</strong> 栈是先进后出，所以先入栈右子树，再入栈左子树，出栈的时候正好是先左子树后右子树。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> List&lt;Integer&gt; <span class="title">preorderTraversal</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">        List&lt;Integer&gt; output = <span class="keyword">new</span> LinkedList&lt;Integer&gt;();</span><br><span class="line">        Stack&lt;TreeNode&gt; stack = <span class="keyword">new</span> Stack&lt;TreeNode&gt;();</span><br><span class="line">        <span class="keyword">if</span> (root == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> output;</span><br><span class="line">        &#125;</span><br><span class="line">        stack.push(root);</span><br><span class="line">        <span class="keyword">while</span> (!stack.isEmpty()) &#123;</span><br><span class="line">            TreeNode tempNode = stack.pop();</span><br><span class="line">            output.add(tempNode.val);</span><br><span class="line">            <span class="keyword">if</span> (tempNode.right != <span class="keyword">null</span>) &#123;</span><br><span class="line">                stack.push(tempNode.right);</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (tempNode.left != <span class="keyword">null</span>) &#123;</span><br><span class="line">                stack.push(tempNode.left);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;     </span><br><span class="line">        <span class="keyword">return</span> output;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="94-二叉树的中序遍历">94. 二叉树的中序遍历</h2>
<p><a href="https://leetcode-cn.com/problems/binary-tree-inorder-traversal/" target="_blank" rel="noopener">二叉树的中序遍历</a></p>
<p><strong>递归</strong> 左根右</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    List&lt;Integer&gt; output = <span class="keyword">new</span> LinkedList&lt;Integer&gt;();</span><br><span class="line">    <span class="function"><span class="keyword">public</span> List&lt;Integer&gt; <span class="title">inorderTraversal</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">        MidOrder(root);</span><br><span class="line">        <span class="keyword">return</span> output;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">MidOrder</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (root == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        MidOrder(root.left);</span><br><span class="line">        output.add(root.val);</span><br><span class="line">        MidOrder(root.right);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>迭代</strong> 利用栈实现，先找到二叉树的最左叶子节点对其访问，然后退回上一个节点访问，如果有右子树则对其右子树同样地进行找到最左叶子节点操作。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> List&lt;Integer&gt; <span class="title">inorderTraversal</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">        List&lt;Integer&gt; output = <span class="keyword">new</span> LinkedList&lt;Integer&gt;();</span><br><span class="line">        Stack&lt;TreeNode&gt; stack = <span class="keyword">new</span> Stack&lt;TreeNode&gt;();</span><br><span class="line">        TreeNode tempNode = root;</span><br><span class="line">        <span class="keyword">while</span> (tempNode != <span class="keyword">null</span> || !stack.isEmpty()) &#123;</span><br><span class="line">            <span class="keyword">while</span> (tempNode != <span class="keyword">null</span>) &#123;</span><br><span class="line">                stack.push(tempNode);</span><br><span class="line">                tempNode = tempNode.left;</span><br><span class="line">            &#125;</span><br><span class="line">            tempNode = stack.pop();</span><br><span class="line">            output.add(tempNode.val);</span><br><span class="line">            tempNode = tempNode.right;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> output;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="145-二叉树的后序遍历">145. 二叉树的后序遍历</h2>
<p><a href="https://leetcode-cn.com/problems/binary-tree-postorder-traversal/" target="_blank" rel="noopener">二叉树的后序遍历</a></p>
<p><strong>递归</strong> 左右根</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    List&lt;Integer&gt; output = <span class="keyword">new</span> LinkedList&lt;Integer&gt;();</span><br><span class="line">    <span class="function"><span class="keyword">public</span> List&lt;Integer&gt; <span class="title">postorderTraversal</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">        afterOrder(root);</span><br><span class="line">        <span class="keyword">return</span> output;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">afterOrder</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (root == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        afterOrder(root.left);</span><br><span class="line">        afterOrder(root.right);</span><br><span class="line">        output.add(root.val);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>迭代</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> List&lt;Integer&gt; <span class="title">postorderTraversal</span><span class="params">(TreeNode root)</span> </span>&#123;       </span><br><span class="line">        List&lt;Integer&gt; output = <span class="keyword">new</span> LinkedList&lt;Integer&gt;();</span><br><span class="line">        Stack&lt;TreeNode&gt; stack = <span class="keyword">new</span> Stack&lt;TreeNode&gt;();</span><br><span class="line">        <span class="keyword">if</span> (root == <span class="keyword">null</span>) &#123;</span><br><span class="line">		<span class="keyword">return</span> output;</span><br><span class="line">	    &#125;</span><br><span class="line">        <span class="comment">// cur 记录上一次访问对象</span></span><br><span class="line">        TreeNode cur = root;</span><br><span class="line">        stack.push(root);</span><br><span class="line">        <span class="keyword">while</span> (!stack.isEmpty()) &#123;</span><br><span class="line">            TreeNode tempNode = stack.peek();</span><br><span class="line">            <span class="keyword">if</span> (tempNode.left != <span class="keyword">null</span> &amp;&amp; tempNode.left != cur &amp;&amp; tempNode.right != cur) &#123;</span><br><span class="line">                <span class="comment">// 左子树不为空，且左子树未被访问（防止左子树访问后退回父节点又访问左子树）</span></span><br><span class="line">                <span class="comment">// 且右子树不为空（防止左右子树都访问后退回父节点又接着访问）</span></span><br><span class="line">                stack.push(tempNode.left);</span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (tempNode.right != <span class="keyword">null</span> &amp;&amp; tempNode.right != cur) &#123;</span><br><span class="line">                <span class="comment">// 右子树不为空且右子树未被访问</span></span><br><span class="line">                stack.push(tempNode.right);</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                tempNode = stack.pop();</span><br><span class="line">                output.add(tempNode.val);</span><br><span class="line">                cur = tempNode;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> output;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="102-二叉树的层序遍历">102.  二叉树的层序遍历</h2>
<p><a href="https://leetcode-cn.com/problems/binary-tree-level-order-traversal/" target="_blank" rel="noopener">二叉树的层序遍历</a></p>
<blockquote>
<p>给定一个二叉树，返回按照 <strong>层序遍历</strong> 得到的节点值</p>
</blockquote>
<p>用一个队列记录一层的元素，然后扫描这一层的元素，并把下一层的元素添加到队列中，同时将本层的元素添加到 List 集合中去。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="keyword">public</span> List&lt;List&lt;Integer&gt;&gt; levelOrder(TreeNode root) &#123;       </span><br><span class="line">        Queue&lt;TreeNode&gt; queue = <span class="keyword">new</span> LinkedList&lt;TreeNode&gt;();</span><br><span class="line">        List&lt;List&lt;Integer&gt;&gt; resList = <span class="keyword">new</span> LinkedList&lt;List&lt;Integer&gt;&gt;();</span><br><span class="line">        <span class="keyword">if</span> (root != <span class="keyword">null</span>) &#123;</span><br><span class="line">            queue.add(root);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">while</span> (! queue.isEmpty()) &#123;</span><br><span class="line">            <span class="keyword">int</span> size = queue.size();</span><br><span class="line">            LinkedList&lt;Integer&gt; tempList = <span class="keyword">new</span> LinkedList&lt;Integer&gt;();</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; size; i++) &#123;</span><br><span class="line">                TreeNode tempNode = queue.poll();</span><br><span class="line">                tempList.add(tempNode.val);</span><br><span class="line">                <span class="keyword">if</span> (tempNode.left != <span class="keyword">null</span>) &#123;</span><br><span class="line">                    queue.add(tempNode.left);</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">if</span> (tempNode.right != <span class="keyword">null</span>) &#123;</span><br><span class="line">                    queue.add(tempNode.right);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            resList.add(tempList);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> resList;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="107-二叉树的层次遍历-ii">107. 二叉树的层次遍历 II</h2>
<p><a href="https://leetcode-cn.com/problems/binary-tree-level-order-traversal-ii/" target="_blank" rel="noopener">二叉树的层次遍历 II</a></p>
<blockquote>
<p>给定一个二叉树，返回其节点值自底向上的层次遍历。 （即按从叶子节点所在层到根节点所在的层，逐层从左向右遍历）</p>
</blockquote>
<p>同102类似，利用队列进行层次遍历，不同的是在插入时使用头插的方法记录每一层的节点。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="keyword">public</span> List&lt;List&lt;Integer&gt;&gt; levelOrderBottom(TreeNode root) &#123;</span><br><span class="line">        List&lt;List&lt;Integer&gt;&gt; resList = <span class="keyword">new</span> LinkedList&lt;List&lt;Integer&gt;&gt;();</span><br><span class="line">        Queue&lt;TreeNode&gt; queue = <span class="keyword">new</span> LinkedList&lt;TreeNode&gt;();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (root != <span class="keyword">null</span>) &#123;</span><br><span class="line">            queue.add(root);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">while</span> (!queue.isEmpty()) &#123;</span><br><span class="line">            <span class="keyword">int</span> size = queue.size();</span><br><span class="line">            List&lt;Integer&gt; tempList = <span class="keyword">new</span> LinkedList&lt;Integer&gt;();</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; size; i++) &#123;</span><br><span class="line">                TreeNode tempNode = queue.poll();</span><br><span class="line">                tempList.add(tempNode.val);</span><br><span class="line">                <span class="keyword">if</span> (tempNode.left != <span class="keyword">null</span>) &#123;</span><br><span class="line">                    queue.add(tempNode.left);</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">if</span> (tempNode.right != <span class="keyword">null</span>) &#123;</span><br><span class="line">                    queue.add(tempNode.right);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">// 头插</span></span><br><span class="line">            resList.add(<span class="number">0</span>, tempList);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> resList;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="103-二叉树的锯齿形层次遍历">103. 二叉树的锯齿形层次遍历</h2>
<p><a href="https://leetcode-cn.com/problems/binary-tree-zigzag-level-order-traversal/" target="_blank" rel="noopener">二叉树的锯齿形层次遍历</a></p>
<p>层序遍历的变形，定义一个变量来记录当前层次的遍历是从左往右还是从右往左。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="keyword">public</span> List&lt;List&lt;Integer&gt;&gt; zigzagLevelOrder(TreeNode root) &#123;</span><br><span class="line">        List&lt;List&lt;Integer&gt;&gt; output = <span class="keyword">new</span> LinkedList&lt;List&lt;Integer&gt;&gt;();</span><br><span class="line">        Queue&lt;TreeNode&gt; queue = <span class="keyword">new</span> LinkedList&lt;TreeNode&gt;();</span><br><span class="line">        <span class="keyword">if</span> (root == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> output;</span><br><span class="line">        &#125;</span><br><span class="line">        queue.add(root);</span><br><span class="line">        <span class="keyword">boolean</span> sequence = <span class="keyword">true</span>;</span><br><span class="line">        <span class="keyword">while</span> (! queue.isEmpty()) &#123;</span><br><span class="line">            <span class="keyword">int</span> size = queue.size();</span><br><span class="line">            List&lt;Integer&gt; tempList = <span class="keyword">new</span> LinkedList&lt;Integer&gt;();</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; size; i++) &#123;</span><br><span class="line">                TreeNode tempNode = queue.poll();</span><br><span class="line">                <span class="keyword">if</span> (sequence) &#123;</span><br><span class="line">                    tempList.add(tempNode.val);</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    tempList.add(<span class="number">0</span>, tempNode.val);</span><br><span class="line">                &#125;</span><br><span class="line"></span><br><span class="line">                <span class="keyword">if</span> (tempNode.left != <span class="keyword">null</span>) &#123;</span><br><span class="line">                    queue.add(tempNode.left);</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">if</span> (tempNode.right != <span class="keyword">null</span>) &#123;</span><br><span class="line">                    queue.add(tempNode.right);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            output.add(tempList);</span><br><span class="line">            sequence = !sequence;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> output;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="104-二叉树的最大深度">104. 二叉树的最大深度</h2>
<p><a href="https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/" target="_blank" rel="noopener">二叉树的最大深度</a></p>
<blockquote>
<p>给定一个二叉树，找出其最大深度。</p>
</blockquote>
<p><strong>思路1：递归。</strong> 已知左右子树的深度为 <code>l</code> 和 <code>r</code> ，那么该二叉树的最大深度为<br>
$$<br>
max(l,r) + 1<br>
$$<br>
而左子树和右子树的最大深度又可以以同样的方式进行计算。递归在访问到空节点时退出。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">maxDepth</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (root == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> Math.max(maxDepth(root.left), maxDepth(root.right)) + <span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>思路2：中序遍历。</strong> 需要作一点的改变是，得记录每一层节点的个数，只有在遍历完当前层次的节点过后，才能算作进入下一层。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">maxDepth</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (root == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">int</span> depth = <span class="number">0</span>;</span><br><span class="line">        Queue&lt;TreeNode&gt; queue = <span class="keyword">new</span> LinkedList&lt;TreeNode&gt;();</span><br><span class="line">        queue.add(root);</span><br><span class="line">        <span class="keyword">while</span> (!queue.isEmpty()) &#123;</span><br><span class="line">            <span class="keyword">int</span> size = queue.size();</span><br><span class="line">            <span class="keyword">while</span> (size &gt; <span class="number">0</span>) &#123;</span><br><span class="line">                TreeNode temp = queue.poll();</span><br><span class="line">                <span class="keyword">if</span> (temp.left != <span class="keyword">null</span>) &#123;</span><br><span class="line">                    queue.add(temp.left);</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">if</span> (temp.right != <span class="keyword">null</span>) &#123;</span><br><span class="line">                    queue.add(temp.right);</span><br><span class="line">                &#125;</span><br><span class="line">                size--;</span><br><span class="line">            &#125;</span><br><span class="line">            depth++;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> depth;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="110-平衡二叉树">110. 平衡二叉树</h2>
<p><a href="https://leetcode-cn.com/problems/balanced-binary-tree/" target="_blank" rel="noopener">平衡二叉树</a></p>
<blockquote>
<p>判断一棵二叉树是否是高度平衡的二叉树。</p>
</blockquote>
<p>高度平衡二叉树的定义：一个二叉树<em>每个节点</em> 的左右两个子树的高度差的绝对值不超过1。</p>
<p><strong>自顶向下：</strong> 首先计算左右子树的高度，如果左右子树的高度差是否不超过 1，再分别递归地遍历左右子节点，并判断左子树和右子树是否平衡。这是一个自顶向下的递归的过程。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isBalanced</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (root == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> Math.abs(maxDepth(root.left) - maxDepth(root.right)) &lt; <span class="number">2</span> &amp;&amp; isBalanced(root.left) &amp;&amp; isBalanced(root.right);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">maxDepth</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (root == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> Math.max(maxDepth(root.left), maxDepth(root.right)) + <span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>自底向上：</strong></p>
<p>自顶向下对于同一个节点，函数 <code>maxDepth</code> 会被重复调用，会导致时间复杂度高。使用自底向上的做法，对每个节点只会调用函数 <code>maxDepth</code> 一次。</p>
<p>对于当前遍历到的节点，先递归地判断其左右子树是否平衡，再判断以当前节点为根的子树是否平衡。如果一棵子树是平衡的，则返回其高度（高度一定是非负整数），否则返回 -1。如果存在一棵子树不平衡，则整个二叉树一定不平衡。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isBalanced</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">       <span class="keyword">return</span> maxDepth1(root) &gt;= <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">maxDepth1</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (root == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">int</span> leftHeight = maxDepth1(root.left);</span><br><span class="line">        <span class="keyword">int</span> rightHeight = maxDepth1(root.right);</span><br><span class="line">        <span class="keyword">if</span> (leftHeight == -<span class="number">1</span> || rightHeight == -<span class="number">1</span> || Math.abs(leftHeight - rightHeight) &gt; <span class="number">1</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> -<span class="number">1</span>;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> Math.max(leftHeight, rightHeight) + <span class="number">1</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="124-二叉树中的最大路径和">124. 二叉树中的最大路径和</h2>
<p><a href="https://leetcode-cn.com/problems/binary-tree-maximum-path-sum/" target="_blank" rel="noopener">二叉树中的最大路径和</a></p>
<blockquote>
<p>给一颗非空的二叉树，返回其最大路径和。</p>
</blockquote>
<p>主要使用递归的思想。完成一个函数 <code>maxGain(node)</code> ，计算二叉树中的一个节点的最大贡献值，即以该节点为根节点的子树中寻找以该节点为起点的一条路径，使得该路径上的节点值之和最大。</p>
<p>具体而言，计算如下：</p>
<ul>
<li>空节点的最大贡献为0</li>
<li>非空节点的最大贡献等于节点值与其子节点中的最大贡献值之和</li>
</ul>
<p>使用全局变量 <code>maxSum</code> 来存储最大路径和，在递归过程中更新它的值。</p>
<p><strong>节点的贡献值是节点所在的路径！对于当前节点的贡献值是节点值+MAX（左节点的最大贡献，右节点的最大贡献）。</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> maxSum = Integer.MIN_VALUE;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">maxPathSum</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">        maxGain(root);</span><br><span class="line">        <span class="keyword">return</span> maxSum;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">maxGain</span><span class="params">(TreeNode node)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (node == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 递归计算左右子节点的最大贡献值</span></span><br><span class="line">        <span class="comment">// 只有在最大贡献值大于 0 时，才会选取对应子节点</span></span><br><span class="line">        <span class="keyword">int</span> leftGain = Math.max(maxGain(node.left), <span class="number">0</span>);</span><br><span class="line">        <span class="keyword">int</span> rightGain = Math.max(maxGain(node.right), <span class="number">0</span>);</span><br><span class="line">        <span class="comment">// 节点的最大路径和取决于该节点的值与该节点的左右子节点的最大贡献值</span></span><br><span class="line">        <span class="keyword">int</span> priceNewpath = node.val + leftGain + rightGain;</span><br><span class="line">        <span class="comment">// 更新答案</span></span><br><span class="line">        maxSum = Math.max(maxSum, priceNewpath);</span><br><span class="line">        <span class="comment">// 返回节点的最大贡献值</span></span><br><span class="line">        <span class="keyword">return</span> node.val + Math.max(leftGain, rightGain);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="236-二叉树的最近公共祖先">236. 二叉树的最近公共祖先</h2>
<p><a href="https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/" target="_blank" rel="noopener">二叉树的最近公共祖先</a></p>
<blockquote>
<p>给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。</p>
</blockquote>
<p><strong>祖先的定义：</strong> 若节点 <em>p</em> 在节点 <em>root</em> 的左（右）子树中，或 <em>p = root</em> ，则称 <em>root</em>  是 <em>p</em> 的祖先。</p>
<p>**最近公共祖先的定义：**设节点 <em>root</em> 为节点 <em>p, q</em> 的某公共祖先，若其左子节点 <em>root.left</em> 和右子节点 <em>root.right</em> 都不是 <em>p, q</em> 的公共祖先，则称 <em>root</em> 是 “最近的公共祖先”。</p>
<p>根据以上定义，若 <em>root</em> 是 <em>p, q</em> 的 <strong>最近公共祖先</strong> ，则只可能为以下情况之一：</p>
<ul>
<li><em>p</em> 和 <em>q</em> 在root的子树中，且分列 <em>root</em> 的 <strong>异侧</strong> （即分别在左、右子树中）；</li>
<li><em>p = root</em> ，且 <em>q</em> 在 <em>root</em> 的左或右子树中；</li>
<li><em>q = root</em> ，且 <em>p</em> 在 <em>root</em> 的左或右子树中；</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> TreeNode <span class="title">lowestCommonAncestor</span><span class="params">(TreeNode root, TreeNode p, TreeNode q)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 越过叶子节点 或 找到其中一个节点</span></span><br><span class="line">        <span class="keyword">if</span> (root == <span class="keyword">null</span> || root.val == p.val || root.val == q.val) &#123;</span><br><span class="line">            <span class="keyword">return</span> root;</span><br><span class="line">        &#125;</span><br><span class="line">   </span><br><span class="line">        TreeNode left = lowestCommonAncestor(root.left, p, q);</span><br><span class="line">        TreeNode right = lowestCommonAncestor(root.right, p, q);</span><br><span class="line">        </span><br><span class="line">        </span><br><span class="line">		<span class="comment">// 左、右子树都不为空，则表明 p 和 q 在 root 的异侧，该节点是最近公共祖先</span></span><br><span class="line">        <span class="keyword">if</span> (left != <span class="keyword">null</span> &amp;&amp; right != <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> root;</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (left != <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="comment">// left != null &amp;&amp; right == null</span></span><br><span class="line">            <span class="comment">// p 和 q 都不在 root 的右侧，直接返回 left</span></span><br><span class="line">            <span class="keyword">return</span> left;</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (right != <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="comment">// left == null &amp;&amp; right != null</span></span><br><span class="line">            <span class="keyword">return</span> right;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="comment">// 同时为空，说明 root 的左右子树都不包含 p 和 q</span></span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="98-验证二叉搜索树">98. 验证二叉搜索树</h2>
<p><a href="https://leetcode-cn.com/problems/validate-binary-search-tree/" target="_blank" rel="noopener">验证二叉搜索树</a></p>
<blockquote>
<p>假设一个二叉搜索树具有如下特征：</p>
<ul>
<li>节点的左子树只包含<strong>小于</strong>当前节点的数。</li>
<li>节点的右子树只包含<strong>大于</strong>当前节点的数。</li>
<li>所有左子树和右子树自身必须也是二叉搜索树。</li>
</ul>
<p>给定一个二叉树，判断其是否是一个有效的二叉搜索树</p>
</blockquote>
<p><strong>中序遍历递归</strong> 利用 <code>pre</code> 变量记录中序遍历中的前一个值大小。因为中序遍历的顺序是左根右，遍历时，判断当前节点是否大于中序遍历的前一个节点，如果大于，说明满足 BST，继续遍历；否则直接返回 <code>false</code>。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="keyword">long</span> pre = Long.MIN_VALUE;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isValidBST</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (root == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 访问左子树</span></span><br><span class="line">        <span class="keyword">if</span> (!isValidBST(root.left)) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 访问当前节点：如果当前节点小于等于中序遍历的前一个节点，说明不满足BST，返回 false；否则继续遍历。</span></span><br><span class="line">        <span class="keyword">if</span> (root.val &lt;= pre) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        pre = root.val;</span><br><span class="line">        <span class="comment">// 访问右子树</span></span><br><span class="line">        <span class="keyword">return</span> isValidBST(root.right);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>中序遍历迭代</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isValidBST</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">        Stack&lt;TreeNode&gt; stack = <span class="keyword">new</span> Stack&lt;TreeNode&gt;();</span><br><span class="line">        <span class="keyword">long</span> pre = Long.MIN_VALUE;</span><br><span class="line">        TreeNode tempNode = root;</span><br><span class="line">        <span class="keyword">while</span>(tempNode != <span class="keyword">null</span> || !stack.isEmpty()) &#123;</span><br><span class="line">            <span class="keyword">while</span> (tempNode != <span class="keyword">null</span>) &#123;</span><br><span class="line">                stack.push(tempNode);</span><br><span class="line">                tempNode = tempNode.left;</span><br><span class="line">            &#125;</span><br><span class="line">            tempNode = stack.pop();</span><br><span class="line">            <span class="keyword">if</span> (pre &gt;= tempNode.val) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            pre = tempNode.val;</span><br><span class="line">            tempNode = tempNode.right;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="701-二叉搜索树中的插入操作">701. 二叉搜索树中的插入操作</h2>
<p><a href="https://leetcode-cn.com/problems/insert-into-a-binary-search-tree/" target="_blank" rel="noopener">二叉搜索树中的插入操作</a></p>
<blockquote>
<p>给定二叉搜索树（BST）的根节点和要插入树中的值，将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。保证原始二叉搜索树中不存在新值。</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> TreeNode <span class="title">insertIntoBST</span><span class="params">(TreeNode root, <span class="keyword">int</span> val)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (root == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">new</span> TreeNode(val);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (val &lt; root.val) &#123;</span><br><span class="line">            root.left = insertIntoBST(root.left, val);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            root.right = insertIntoBST(root.right, val);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> root;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="450-删除二叉搜索树中的节点">450. 删除二叉搜索树中的节点</h2>
<p><a href="https://leetcode-cn.com/problems/delete-node-in-a-bst/" target="_blank" rel="noopener">删除二叉搜索树中的节点</a></p>
<blockquote>
<p>给定一个二叉搜索树的根节点 root 和一个值 key，删除二叉搜索树中的 key 对应的节点，并保证二叉搜索树的性质不变。返回二叉搜索树（有可能被更新）的根节点的引用。</p>
</blockquote>
<p>按照二叉搜索树的规则去寻找需要删除的节点，找到后可以分为三种情况：</p>
<ul>
<li>若待删除节点为叶子节点：直接删除该节点</li>
<li>若待删除节点有右子树：用该节点的后继节点来替代，且删除后继节点</li>
<li>若待删除节点只有左子树：用该节点的前驱节点来替代，且删除前驱节点</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> TreeNode <span class="title">deleteNode</span><span class="params">(TreeNode root, <span class="keyword">int</span> key)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (root == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> root;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (key &lt; root.val) &#123;</span><br><span class="line">            root.left = deleteNode(root.left, key);</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (key &gt; root.val) &#123;</span><br><span class="line">            root.right = deleteNode(root.right, key);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="comment">// 如果是叶子节点，直接删除</span></span><br><span class="line">            <span class="keyword">if</span> (isLeaf(root)) &#123;</span><br><span class="line">                root = <span class="keyword">null</span>;</span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (root.right != <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="comment">// 如果有右子树，找到后继节点，替换并删除后继节点</span></span><br><span class="line">                root.val = aftereNode(root);</span><br><span class="line">                root.right = deleteNode(root.right, root.val);</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="comment">// 如果没有右子树，有左子树，找到前驱节点，替换并删除前驱节点</span></span><br><span class="line">                root.val = beforeNode(root);</span><br><span class="line">                root.left = deleteNode(root.left, root.val);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">return</span> root;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 判断是否为叶子节点</span></span><br><span class="line">    <span class="function"><span class="keyword">boolean</span> <span class="title">isLeaf</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (root.left == <span class="keyword">null</span> &amp;&amp; root.right == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 找到前驱节点的值</span></span><br><span class="line">    <span class="function"><span class="keyword">int</span> <span class="title">beforeNode</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">        TreeNode tempNode = root.left;</span><br><span class="line">        <span class="keyword">while</span> (tempNode.right != <span class="keyword">null</span>) &#123;</span><br><span class="line">            tempNode = tempNode.right;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> tempNode.val;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 找到后继节点的值</span></span><br><span class="line">    <span class="function"><span class="keyword">int</span> <span class="title">aftereNode</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">        TreeNode tempNode = root.right;</span><br><span class="line">        <span class="keyword">while</span> (tempNode.left != <span class="keyword">null</span>) &#123;</span><br><span class="line">            tempNode = tempNode.left;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> tempNode.val;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h1 id="2-链表">2、链表</h1>
<ul>
<li>null 异常处理</li>
<li>哑巴节点</li>
<li>快慢指针</li>
<li>插入一个节点到排序列表</li>
<li>从一个链表中移除一个节点</li>
<li>翻转链表</li>
<li>合并两个链表</li>
<li>找到链表的中间节点</li>
</ul>
<h2 id="83-删除排序链表中的重复元素">83. 删除排序链表中的重复元素</h2>
<p><a href="https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list/" target="_blank" rel="noopener">删除排序链表中的重复元素</a></p>
<blockquote>
<p>给定一个排序链表，删除所有重复的元素，使得每个元素只出现一次。</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> ListNode <span class="title">deleteDuplicates</span><span class="params">(ListNode head)</span> </span>&#123;</span><br><span class="line">        ListNode temp = head;</span><br><span class="line">        <span class="keyword">while</span> (temp != <span class="keyword">null</span> &amp;&amp; temp.next != <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">if</span> (temp.val == temp.next.val) &#123;</span><br><span class="line">                temp.next = temp.next.next;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                temp = temp.next;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> head;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="82-删除排序链表中的重复元素-ii">82. 删除排序链表中的重复元素 II</h2>
<p><a href="https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list-ii/" target="_blank" rel="noopener">删除排序链表中的重复元素 II</a></p>
<blockquote>
<p>给定一个排序链表，删除所有含有重复数字的节点，只保留原始链表中 <em>没有重复出现</em> 的数字。</p>
</blockquote>
<p><strong>双指针</strong></p>
<p>建立两个指针 <code>pre</code> 和 <code>tempNode</code> ，<code>pre</code> 记录的是上一个不同值的链表元素，当 <code>tempNode</code> 指向下一个与 <code>pre</code> 指向元素值不相同时，判断两个指针所指向元素是否相邻（即 <code>pre.next == tempNode</code> ）。</p>
<ul>
<li>如果相邻表示 <code>*-&gt;1-&gt;2</code> 这种情况，<code>pre</code> 所指向的 <code>1</code> 能够被插入输出链表</li>
<li>如果不相邻表示 <code>*-&gt;1-&gt;1-&gt;2</code> 这种情况，<code>pre</code> 所指向的 <code>1</code> 不能被插入输出链表，直接更新 <code>pre</code> 指针的位置到 <code>2</code></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> ListNode <span class="title">deleteDuplicates</span><span class="params">(ListNode head)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 建立一个虚拟头结点        </span></span><br><span class="line">        ListNode output = <span class="keyword">new</span> ListNode(-<span class="number">1</span>);</span><br><span class="line">        <span class="comment">// 定义一个尾巴，用于尾插法</span></span><br><span class="line">        ListNode tail = output; </span><br><span class="line">        ListNode pre = head, tempNode = head;</span><br><span class="line">        <span class="keyword">while</span> (tempNode != <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">while</span> (tempNode != <span class="keyword">null</span> &amp;&amp; pre.val == tempNode.val) &#123;</span><br><span class="line">                tempNode = tempNode.next;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (pre.next == tempNode) &#123;</span><br><span class="line">                <span class="comment">// pre 和 tempNode 是邻近节点</span></span><br><span class="line">                <span class="comment">// 说明 pre 和 tempNode 的节点值不同，pre 可以放入output链表</span></span><br><span class="line">                tail.next = pre;</span><br><span class="line">                tail = tail.next;</span><br><span class="line">                tail.next = <span class="keyword">null</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            pre = tempNode;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> output.next;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>递归</strong></p>
<p>递归地处理链表头，确保没有重复的。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> ListNode <span class="title">deleteDuplicates</span><span class="params">(ListNode head)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (head == <span class="keyword">null</span> || head.next == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> head;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (head.val == head.next.val) &#123;</span><br><span class="line">            <span class="comment">// 链表的开头就出现重复，while中消除链表头之后的重复，直到第一个不重复</span></span><br><span class="line">            <span class="comment">// 传递第一个不重复的链表节点，变相的删除了重复的链表头。</span></span><br><span class="line">            <span class="keyword">while</span> (head != <span class="keyword">null</span> &amp;&amp; head.next != <span class="keyword">null</span> &amp;&amp; head.val == head.next.val) &#123;</span><br><span class="line">                head.next = head.next.next;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">return</span> deleteDuplicates(head.next);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            head.next = deleteDuplicates(head.next);</span><br><span class="line">            <span class="keyword">return</span> head;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="206-反转链表">206. 反转链表</h2>
<p><a href="https://leetcode-cn.com/problems/reverse-linked-list/" target="_blank" rel="noopener">反转链表</a></p>
<blockquote>
<p>反转一个单链表</p>
</blockquote>
<p><strong>迭代</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> ListNode <span class="title">reverseList</span><span class="params">(ListNode head)</span> </span>&#123;</span><br><span class="line">        ListNode output = <span class="keyword">null</span>;</span><br><span class="line">        ListNode curr = head;</span><br><span class="line">        <span class="keyword">while</span> (curr != <span class="keyword">null</span>) &#123;</span><br><span class="line">            ListNode nextTemp = curr.next;</span><br><span class="line">            curr.next = output;</span><br><span class="line">            output = curr;</span><br><span class="line">            curr = nextTemp;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> output;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>递归</strong></p>
<p>假设链表为 <code>1-&gt;2-&gt;3</code> 当前走到了 <code>2</code> ，此时</p>
<p><code>tempNode = 3</code></p>
<p><code>head = 2-&gt;3</code></p>
<p>于是 <code>head.next.next = head</code> 表示 <code>2-&gt;3-&gt;2</code> ，<code>head.next = null</code> 就变成了 <code>3-&gt;2</code> 实现了反转。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> ListNode <span class="title">reverseList</span><span class="params">(ListNode head)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (head == <span class="keyword">null</span> || head.next == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> head;</span><br><span class="line">        &#125;</span><br><span class="line">        ListNode tempNode = reverseList(head.next);</span><br><span class="line">        head.next.next = head;</span><br><span class="line">        head.next = <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">return</span> tempNode;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="92-反转链表-ii">92. 反转链表 II</h2>
<p><a href="https://leetcode-cn.com/problems/reverse-linked-list-ii/" target="_blank" rel="noopener">反转链表 II</a></p>
<blockquote>
<p>反转从位置 <em>m</em> 到 <em>n</em> 的链表。请使用一趟扫描完成反转。</p>
</blockquote>
<p>将链表分为三个部分，需要反转之前，需要反转，需要反转之后。分别用指针 <code>preNode</code> 记录第 <code>m-1</code> 个元素，即第一个需要反转的元素的前一个元素，用来作为反转元素链表的头指针使用；需要反转的元素才用头插法，插到 <code>preNode</code> 所指向元素的后面，且利用指针 <code>tailNode</code> 记录元素反转过后被放到末尾的元素，反转完所有待反转元素后，再用 <code>tailNode</code> 连接反转部分和需要反转之后的部分。</p>
<p>例如： <code>1-&gt;2-&gt;3-&gt;4-&gt;5-&gt;NULL，m=2，n=4</code> ，此时 <code>preNode</code> 指向元素 <code>1</code>， <code>tailNode</code> 指向元素 <code>2</code>，等到反转完所有元素后， <code>tailNode</code> 将指向元素 <code>5</code>。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> ListNode <span class="title">reverseBetween</span><span class="params">(ListNode head, <span class="keyword">int</span> m, <span class="keyword">int</span> n)</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// </span></span><br><span class="line">        ListNode preNode = <span class="keyword">null</span>;</span><br><span class="line">        ListNode tailNode = <span class="keyword">null</span>;</span><br><span class="line">        ListNode output = <span class="keyword">new</span> ListNode(-<span class="number">1</span>);</span><br><span class="line">        ListNode curNode = output;</span><br><span class="line">        curNode.next = head;</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; m - <span class="number">1</span>; i++) &#123;</span><br><span class="line">            curNode = curNode.next;</span><br><span class="line">        &#125;</span><br><span class="line">        preNode = curNode; <span class="comment">// 指向第 m-1 个元素，作为反转元素的头</span></span><br><span class="line">        tailNode = preNode.next; <span class="comment">// 记录反转后的尾巴元素，以便和第 m+1 个元素连接起来</span></span><br><span class="line">        curNode = curNode.next; <span class="comment">// 指向第 m 个元素</span></span><br><span class="line">        <span class="comment">// 采用头插法将需要反转的元素进行反转</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = m; i &lt;= n; i++) &#123;</span><br><span class="line">            ListNode tempNode = curNode.next;</span><br><span class="line">            curNode.next = preNode.next;</span><br><span class="line">            preNode.next = curNode;</span><br><span class="line">            curNode = tempNode;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 将反转的尾巴元素指向后面不需要反转的元素</span></span><br><span class="line">        tailNode.next = curNode;</span><br><span class="line">        <span class="keyword">return</span> output.next;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="21-合并两个有序链表">21. 合并两个有序链表</h2>
<p><a href="https://leetcode-cn.com/problems/merge-two-sorted-lists/" target="_blank" rel="noopener">合并两个有序链表</a></p>
<blockquote>
<p>将两个升序链表合并为一个新的 <strong>升序</strong> 链表并返回</p>
</blockquote>
<p><strong>递归</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> ListNode <span class="title">mergeTwoLists</span><span class="params">(ListNode l1, ListNode l2)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (l1 == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> l2;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">else</span> <span class="keyword">if</span> (l2 == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> l1;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">else</span> <span class="keyword">if</span> (l1.val &lt; l2.val) &#123;</span><br><span class="line">            l1.next = mergeTwoLists(l1.next, l2);</span><br><span class="line">            <span class="keyword">return</span> l1;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">else</span> &#123;</span><br><span class="line">            l2.next = mergeTwoLists(l1, l2.next);</span><br><span class="line">            <span class="keyword">return</span> l2;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>迭代</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> ListNode <span class="title">mergeTwoLists</span><span class="params">(ListNode l1, ListNode l2)</span> </span>&#123;</span><br><span class="line">        ListNode prehead = <span class="keyword">new</span> ListNode(-<span class="number">1</span>);</span><br><span class="line"></span><br><span class="line">        ListNode prev = prehead;</span><br><span class="line">        <span class="keyword">while</span> (l1 != <span class="keyword">null</span> &amp;&amp; l2 != <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">if</span> (l1.val &lt;= l2.val) &#123;</span><br><span class="line">                prev.next = l1;</span><br><span class="line">                l1 = l1.next;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                prev.next = l2;</span><br><span class="line">                l2 = l2.next;</span><br><span class="line">            &#125;</span><br><span class="line">            prev = prev.next;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 合并后 l1 和 l2 最多只有一个还未被合并完，我们直接将链表末尾指向未合并完的链表即可</span></span><br><span class="line">        prev.next = l1 == <span class="keyword">null</span> ? l2 : l1;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> prehead.next;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="86-分隔链表">86. 分隔链表</h2>
<p><a href="https://leetcode-cn.com/problems/partition-list/" target="_blank" rel="noopener">分隔链表</a></p>
<blockquote>
<p>给定一个链表和一个特定值 <em>x</em>，对链表进行分隔，使得所有小于 <em>x</em> 的节点都在大于或等于 <em>x</em> 的节点之前。 保留两个分区中每个节点的初试相对位置。</p>
</blockquote>
<p><strong>模拟</strong></p>
<p>记录第一个大于或等于 <code>x</code> 的元素的前一个元素为 <code>pointNode</code> ，往后遍历，每次发现小于 <code>x</code> 的元素时，先把该元素从当前位置取出，再将该元素插入到 <code>pointNode</code> 的后面，为了保证每个节点的初试相对位置， <code>pointNode</code> 相应的往后移动一位。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> ListNode <span class="title">partition</span><span class="params">(ListNode head, <span class="keyword">int</span> x)</span> </span>&#123;</span><br><span class="line">        ListNode output = <span class="keyword">new</span> ListNode(Integer.MIN_VALUE);</span><br><span class="line">        output.next = head;</span><br><span class="line">        ListNode curNode = output;</span><br><span class="line">        ListNode preNode = output;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 找到第一个大于或等于 x 的元素的前一个，并用 pointNode 标记</span></span><br><span class="line">        <span class="keyword">while</span> (curNode != <span class="keyword">null</span> &amp;&amp; curNode.val &lt; x) &#123;</span><br><span class="line">            preNode = curNode;</span><br><span class="line">            curNode = curNode.next;</span><br><span class="line">        &#125;</span><br><span class="line">        ListNode pointNode = preNode;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 往后遍历，发现小于 x 的元素，那么往前插入到 pointNode 的后面，为了符合题目，每次插入pointNode应当往后移一位</span></span><br><span class="line">        <span class="keyword">while</span> (curNode != <span class="keyword">null</span>) &#123;</span><br><span class="line">            ListNode tempNode = curNode.next;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> (curNode.val &lt; x) &#123;</span><br><span class="line">                <span class="comment">// 需要插入，此时的preNode不改变</span></span><br><span class="line">                preNode.next = curNode.next;</span><br><span class="line">                curNode.next = pointNode.next;</span><br><span class="line">                pointNode.next = curNode;</span><br><span class="line">                pointNode = pointNode.next;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                preNode = curNode;</span><br><span class="line">            &#125;</span><br><span class="line">            curNode = tempNode;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> output.next;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>拆分再拼接</strong></p>
<p>将链表拆分为小于 <code>x</code> 的一部分，和大于等于 <code>x</code> 的一部分，然后再将两部分拼接起来。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> ListNode <span class="title">partition</span><span class="params">(ListNode head, <span class="keyword">int</span> x)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 链表less记录小于x的元素</span></span><br><span class="line">        ListNode less = <span class="keyword">new</span> ListNode(<span class="number">0</span>);</span><br><span class="line">        ListNode ptr1 = less;</span><br><span class="line">        <span class="comment">// 链表greatOrEqual记录大于等于x的元素</span></span><br><span class="line">        ListNode greatOrEqual = <span class="keyword">new</span> ListNode(<span class="number">0</span>);</span><br><span class="line">        ListNode ptr2 = greatOrEqual;</span><br><span class="line">        <span class="keyword">while</span> (head != <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">if</span> (head.val &lt; x) &#123;</span><br><span class="line">                ptr1.next = <span class="keyword">new</span> ListNode(head.val);</span><br><span class="line">                ptr1 = ptr1.next;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                ptr2.next = <span class="keyword">new</span> ListNode(head.val);</span><br><span class="line">                ptr2 = ptr2.next;</span><br><span class="line">            &#125;</span><br><span class="line">            head = head.next;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 拼接两段链表</span></span><br><span class="line">        ptr1.next = greatOrEqual.next;</span><br><span class="line">        <span class="keyword">return</span> less.next;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="148-排序链表">148. 排序链表</h2>
<p><a href="https://leetcode-cn.com/problems/sort-list/" target="_blank" rel="noopener">排序链表</a></p>
<blockquote>
<p>在 <em>O</em>(<em>n</em> log <em>n</em>) 时间复杂度和常数级空间复杂度下，对链表进行排序。</p>
</blockquote>
<p><strong>递归</strong> 但是空间不满足常数级</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 知识点1：归并排序的整体思想</span></span><br><span class="line"><span class="comment"> * 知识点2：找到一个链表的中间节点的方法</span></span><br><span class="line"><span class="comment"> * 知识点3：合并两个已排好序的链表为一个新的有序链表</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> ListNode <span class="title">sortList</span><span class="params">(ListNode head)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span>(head==<span class="keyword">null</span> || head.next==<span class="keyword">null</span>) <span class="keyword">return</span> head;</span><br><span class="line">        ListNode slow = head; <span class="comment">//慢指针</span></span><br><span class="line">        ListNode fast = head.next; <span class="comment">//快指针</span></span><br><span class="line">        </span><br><span class="line">        <span class="keyword">while</span>(fast!=<span class="keyword">null</span> &amp;&amp; fast.next!=<span class="keyword">null</span>)&#123; <span class="comment">//快慢指针找到链表中点</span></span><br><span class="line">            slow = slow.next; <span class="comment">//慢指针走一步</span></span><br><span class="line">            fast = fast.next.next; <span class="comment">//快指针走两步</span></span><br><span class="line">        &#125;</span><br><span class="line">        ListNode rightHead = slow.next; <span class="comment">//链表第二部分的头节点</span></span><br><span class="line">        slow.next = <span class="keyword">null</span>; <span class="comment">//cut 链表</span></span><br><span class="line">        </span><br><span class="line">        ListNode left = sortList(head); <span class="comment">//递归排序前一段链表</span></span><br><span class="line">        ListNode right = sortList(rightHead); <span class="comment">//递归排序后一段链表</span></span><br><span class="line">        <span class="keyword">return</span> merge(left,right);</span><br><span class="line">    &#125;  </span><br><span class="line">    <span class="function"><span class="keyword">public</span> ListNode <span class="title">merge</span><span class="params">(ListNode h1,ListNode h2)</span></span>&#123; <span class="comment">//合并两个有序链表</span></span><br><span class="line">        ListNode dummy = <span class="keyword">new</span> ListNode(-<span class="number">1</span>);</span><br><span class="line">        ListNode p = dummy;</span><br><span class="line">        <span class="keyword">while</span>(h1!=<span class="keyword">null</span> &amp;&amp; h2!=<span class="keyword">null</span>)&#123;</span><br><span class="line">            <span class="keyword">if</span>(h1.val &lt; h2.val)&#123;</span><br><span class="line">                p.next = h1;</span><br><span class="line">                h1 = h1.next;</span><br><span class="line">            &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">                p.next = h2;</span><br><span class="line">                h2 = h2.next;</span><br><span class="line">            &#125;</span><br><span class="line">            p = p.next;</span><br><span class="line">        &#125;</span><br><span class="line">        p.next = h1 == <span class="keyword">null</span> ? h2 : h1;</span><br><span class="line">        <span class="keyword">return</span> dummy.next;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>迭代</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> ListNode <span class="title">sortList</span><span class="params">(ListNode head)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> length = getLength(head);</span><br><span class="line">        ListNode dummy = <span class="keyword">new</span> ListNode(-<span class="number">1</span>);</span><br><span class="line">        dummy.next = head;</span><br><span class="line">       </span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">int</span> step = <span class="number">1</span>; step &lt; length; step*=<span class="number">2</span>)&#123; <span class="comment">//依次将链表分成1块，2块，4块...</span></span><br><span class="line">            <span class="comment">//每次变换步长，pre指针和cur指针都初始化在链表头</span></span><br><span class="line">            ListNode pre = dummy; </span><br><span class="line">            ListNode cur = dummy.next;</span><br><span class="line">            <span class="keyword">while</span>(cur!=<span class="keyword">null</span>)&#123;</span><br><span class="line">                ListNode h1 = cur; <span class="comment">//第一部分头 （第二次循环之后，cur为剩余部分头，不断往后把链表按照步长step分成一块一块...）</span></span><br><span class="line">                ListNode h2 = split(h1,step);  <span class="comment">//第二部分头</span></span><br><span class="line">                cur = split(h2,step); <span class="comment">//剩余部分的头</span></span><br><span class="line">                ListNode temp = merge(h1,h2); <span class="comment">//将一二部分排序合并</span></span><br><span class="line">                pre.next = temp; <span class="comment">//将前面的部分与排序好的部分连接</span></span><br><span class="line">                <span class="keyword">while</span>(pre.next!=<span class="keyword">null</span>)&#123;</span><br><span class="line">                    pre = pre.next; <span class="comment">//把pre指针移动到排序好的部分的末尾</span></span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> dummy.next;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getLength</span><span class="params">(ListNode head)</span></span>&#123;</span><br><span class="line">    <span class="comment">//获取链表长度</span></span><br><span class="line">        <span class="keyword">int</span> count = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">while</span>(head!=<span class="keyword">null</span>)&#123;</span><br><span class="line">            count++;</span><br><span class="line">            head=head.next;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> count;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> ListNode <span class="title">split</span><span class="params">(ListNode head,<span class="keyword">int</span> step)</span></span>&#123;</span><br><span class="line">        <span class="comment">//断链操作 返回第二部分链表头</span></span><br><span class="line">        <span class="keyword">if</span>(head==<span class="keyword">null</span>)  <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">        ListNode cur = head;</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">1</span>; i&lt;step &amp;&amp; cur.next!=<span class="keyword">null</span>; i++)&#123;</span><br><span class="line">            cur = cur.next;</span><br><span class="line">        &#125;</span><br><span class="line">        ListNode right = cur.next;</span><br><span class="line">        cur.next = <span class="keyword">null</span>; <span class="comment">//切断连接</span></span><br><span class="line">        <span class="keyword">return</span> right;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> ListNode <span class="title">merge</span><span class="params">(ListNode h1, ListNode h2)</span></span>&#123;</span><br><span class="line">    <span class="comment">//合并两个有序链表</span></span><br><span class="line">        ListNode head = <span class="keyword">new</span> ListNode(-<span class="number">1</span>);</span><br><span class="line">        ListNode p = head;</span><br><span class="line">        <span class="keyword">while</span>(h1!=<span class="keyword">null</span> &amp;&amp; h2!=<span class="keyword">null</span>)&#123;</span><br><span class="line">            <span class="keyword">if</span>(h1.val &lt; h2.val)&#123;</span><br><span class="line">                p.next = h1;</span><br><span class="line">                h1 = h1.next;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">else</span>&#123;</span><br><span class="line">                p.next = h2;</span><br><span class="line">                h2 = h2.next;</span><br><span class="line">            &#125;</span><br><span class="line">            p = p.next;           </span><br><span class="line">        &#125;</span><br><span class="line">        p.next = h1 == <span class="keyword">null</span> ? h2 : h1;</span><br><span class="line">        <span class="keyword">return</span> head.next;     </span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="143-重排链表">143. 重排链表</h2>
<p><a href="https://leetcode-cn.com/problems/reorder-list/" target="_blank" rel="noopener">重排链表</a></p>
<blockquote>
<p>给定一个单链表 L: L0→L1→…→Ln-1→Ln，将其重新排列后变为 L0→Ln→L1→Ln-1→L2→Ln-2→…</p>
</blockquote>
<p><strong>快慢指针</strong> 将链表分为前半部分和后半部分，对后半部分进行翻转，再将两个链表进行交替插入即可。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">reorderList</span><span class="params">(ListNode head)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (head == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> ;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 快、慢指针 slow 和 fast</span></span><br><span class="line">        ListNode slow = head;</span><br><span class="line">        ListNode fast = head.next;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">while</span> (fast != <span class="keyword">null</span> &amp;&amp; fast.next != <span class="keyword">null</span>) &#123;</span><br><span class="line">            slow = slow.next;</span><br><span class="line">            fast = fast.next.next;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 从中间切断，得到前半部分链表 l1 和后半部分链表 l2</span></span><br><span class="line">        ListNode l1 = head;</span><br><span class="line">        ListNode l2 = slow.next;</span><br><span class="line">        slow.next = <span class="keyword">null</span>;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 翻转后半部分链表 l2</span></span><br><span class="line">        l2 = reverse(l2);</span><br><span class="line">        <span class="comment">// l1 和 l2 一人插入一次</span></span><br><span class="line">        head = merge(l1, l2);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function">ListNode <span class="title">reverse</span><span class="params">(ListNode head)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 头插法</span></span><br><span class="line">        ListNode output = <span class="keyword">new</span> ListNode(-<span class="number">1</span>);</span><br><span class="line">        <span class="keyword">while</span> (head != <span class="keyword">null</span>) &#123;</span><br><span class="line">            ListNode nextNode = head.next;</span><br><span class="line">            head.next = output.next;</span><br><span class="line">            output.next = head;</span><br><span class="line">            head = nextNode;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> output.next;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function">ListNode <span class="title">merge</span><span class="params">(ListNode head1, ListNode head2)</span> </span>&#123;</span><br><span class="line">        ListNode output = <span class="keyword">new</span> ListNode(-<span class="number">1</span>);</span><br><span class="line">        ListNode curNode = output;</span><br><span class="line">        <span class="keyword">boolean</span> flag = <span class="keyword">true</span>;</span><br><span class="line">        <span class="keyword">while</span> (head1 != <span class="keyword">null</span> &amp;&amp; head2 != <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">if</span> (flag) &#123;</span><br><span class="line">                flag = <span class="keyword">false</span>;</span><br><span class="line">                curNode.next = head1;</span><br><span class="line">                head1 = head1.next;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                flag = <span class="keyword">true</span>;</span><br><span class="line">                curNode.next = head2;</span><br><span class="line">                head2 = head2.next;</span><br><span class="line">            &#125;</span><br><span class="line">            curNode = curNode.next;</span><br><span class="line">        &#125;</span><br><span class="line">        curNode.next = head1 == <span class="keyword">null</span> ? head2 : head1;</span><br><span class="line">        <span class="keyword">return</span> output.next;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="141-环形链表">141. 环形链表</h2>
<p><a href="https://leetcode-cn.com/problems/linked-list-cycle/" target="_blank" rel="noopener">环形链表</a></p>
<blockquote>
<p>给定一个链表，判断是否有环。</p>
<p>进阶：空间复杂度 O(1) 内解决</p>
</blockquote>
<p><strong>哈希表</strong> 但是不满足空间复杂度 O(1)</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">hasCycle</span><span class="params">(ListNode head)</span> </span>&#123;</span><br><span class="line">        HashSet&lt;ListNode&gt; hashSet = <span class="keyword">new</span> HashSet&lt;ListNode&gt;();</span><br><span class="line">        <span class="keyword">while</span> (head != <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="comment">// hashSet 中已经存在该元素</span></span><br><span class="line">            <span class="keyword">if</span> (!hashSet.add(head)) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            head = head.next;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>快慢指针</strong> 快指针每次移动 <strong>2</strong> 位，慢指针每次移动 <strong>1</strong> 位，如果是循环的链表，那么快慢指针一定会在某个位置相遇。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">hasCycle</span><span class="params">(ListNode head)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (head == <span class="keyword">null</span> || head.next == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        ListNode slow = head;</span><br><span class="line">        ListNode fast = head.next;</span><br><span class="line">        <span class="keyword">while</span> (slow != fast) &#123;</span><br><span class="line">            <span class="keyword">if</span> (fast == <span class="keyword">null</span> || fast.next == <span class="keyword">null</span>) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            slow = slow.next;</span><br><span class="line">            fast = fast.next.next;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="142-环形链表-ii">142. 环形链表 II</h2>
<p><a href="https://leetcode-cn.com/problems/linked-list-cycle-ii/" target="_blank" rel="noopener">环形链表 II</a></p>
<blockquote>
<p>给定一个链表，返回链表开始入环的第一个节点。 如果链表无环，则返回 <code>null</code>。</p>
</blockquote>
<p>首先判断链表是否有环，如果有环再寻找入环的第一个节点。</p>
<p>假设使用快慢指针判断是否有环，那么当有环的情况下，快慢指针重合的地方一定是在环内部（节点 <strong>B</strong>）。假设慢指针一共移动了 <strong>a + b</strong> 次，其中 <strong>a</strong> 是从 <code>head</code> 移动到入环的第一个节点 <strong>A</strong> 的步数， <strong>b</strong> 是从入环的第一个节点 <strong>A</strong> 移动到快慢指针重合的节点 <strong>B</strong> 的步数。快指针移动的步数是慢指针的两倍，所以慢指针再移动 <strong>a + b</strong> 次又能够回到节点 <strong>B</strong>。如果慢指针只移动 <strong>a</strong> 次就能回到入环的第一个节点 <strong>A</strong>，但是对于 <strong>a</strong> 的值是未知的。于是定义一个<code>entranceNode</code> 指针，让它和慢指针同步走，移动 <strong>a</strong> 次，它们相遇的地方必然是入环的第一个节点 <strong>A</strong>。</p>
<p><a href="https://pic.tyzhang.top/image/bLz1" target="_blank" rel="noopener"><img src="https://pic.tyzhang.top/images/2020/11/09/DmliFowkvJhMOVn.png" alt="DmliFowkvJhMOVn.png"></a></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> ListNode <span class="title">detectCycle</span><span class="params">(ListNode head)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (head == <span class="keyword">null</span> || head.next == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 查看是否有环</span></span><br><span class="line">        ListNode slow = head;</span><br><span class="line">        ListNode fast = head;</span><br><span class="line">        <span class="keyword">boolean</span> hasCycle = <span class="keyword">false</span>;</span><br><span class="line">        <span class="keyword">while</span> (fast.next != <span class="keyword">null</span> &amp;&amp; fast.next.next != <span class="keyword">null</span>) &#123;</span><br><span class="line">            slow = slow.next;</span><br><span class="line">            fast = fast.next.next;</span><br><span class="line">            <span class="keyword">if</span> (slow == fast) &#123;</span><br><span class="line">                hasCycle = <span class="keyword">true</span>;</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (hasCycle) &#123;</span><br><span class="line">            <span class="comment">// 找到环的入口</span></span><br><span class="line">            ListNode entranceNode = head;</span><br><span class="line">            <span class="keyword">while</span> (entranceNode != slow) &#123;</span><br><span class="line">                entranceNode = entranceNode.next;</span><br><span class="line">                slow = slow.next;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">return</span> entranceNode;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="234-回文链表">234. 回文链表</h2>
<p><a href="https://leetcode-cn.com/problems/palindrome-linked-list/" target="_blank" rel="noopener">回文链表</a></p>
<blockquote>
<p>判断一个链表是否是回文链表</p>
</blockquote>
<p><strong>双指针 + 栈</strong> 例如 <code>123321</code> 后半部分入栈后从栈顶到栈底为 <code>123</code> ，然后从 <code>head</code> 开始出栈比较</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isPalindrome</span><span class="params">(ListNode head)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (head == <span class="keyword">null</span> || head.next == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        ListNode slow = head;</span><br><span class="line">        ListNode fast = head.next;</span><br><span class="line">        <span class="keyword">while</span> (fast.next != <span class="keyword">null</span> &amp;&amp; fast.next.next != <span class="keyword">null</span>) &#123;</span><br><span class="line">            slow = slow.next;</span><br><span class="line">            fast = fast.next.next;</span><br><span class="line">        &#125;</span><br><span class="line">		</span><br><span class="line">        Stack&lt;Integer&gt; stack = <span class="keyword">new</span> Stack&lt;Integer&gt;();</span><br><span class="line">        <span class="comment">// 指向后半部分的开始节点</span></span><br><span class="line">        ListNode suffixNode = <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">if</span> (getLength(head) % <span class="number">2</span> == <span class="number">0</span>) &#123;</span><br><span class="line">            suffixNode = slow.next;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            suffixNode = slow.next.next;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">while</span> (suffixNode != <span class="keyword">null</span>) &#123;</span><br><span class="line">            stack.push(suffixNode.val);</span><br><span class="line">            suffixNode = suffixNode.next;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">while</span> (!stack.isEmpty()) &#123;</span><br><span class="line">            <span class="keyword">if</span> (head.val != stack.pop()) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            head = head.next;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getLength</span><span class="params">(ListNode head)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> length = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">while</span> (head != <span class="keyword">null</span>) &#123;</span><br><span class="line">            head = head.next;</span><br><span class="line">            length++;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> length;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>反转链表 + 双指针</strong> 空间复杂度 O(1) 时间复杂度 O(n)</p>
<ol>
<li>找到前半部分链表的尾节点。</li>
<li>反转后半部分链表。</li>
<li>判断是否为回文。</li>
<li>恢复链表。</li>
<li>返回结果。</li>
</ol>
<h2 id="138-复制带随机指针的链表">138. 复制带随机指针的链表</h2>
<p><a href="https://leetcode-cn.com/problems/copy-list-with-random-pointer/" target="_blank" rel="noopener">复制带随机指针的链表</a></p>
<p><strong>思路:</strong></p>
<p>第一遍复制节点的 <code>val</code> ，<code>next</code> 和 <code>random</code> 暂时为空，并将源节点和克隆节点形成映射存放在一个 HashMap 中。</p>
<p>第二遍利用 HashMap，将克隆节点对应的 <code>next</code> 和 <code>random</code> 从 HashMap中找出来。比如 curNode 和 curNode.next，它们都在 HashMap 中存放了克隆的节点，于是第二遍复制时把 curNode.next 的克隆节点连接到 curNode 的克隆节点后面即可。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> Node <span class="title">copyRandomList</span><span class="params">(Node head)</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 先创建一个链表，用Map映射当前的node和新的node</span></span><br><span class="line">    Map&lt;Node, Node&gt; map = <span class="keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line">    <span class="comment">// 遍历链表，将原节点作为key，拷贝节点作为value保存在map中</span></span><br><span class="line">    Node curNode = head;</span><br><span class="line">    <span class="keyword">while</span> (curNode != <span class="keyword">null</span>) &#123;</span><br><span class="line">        map.put(curNode, <span class="keyword">new</span> Node(curNode.val));</span><br><span class="line">        curNode = curNode.next;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 复制链表</span></span><br><span class="line">    curNode = head;</span><br><span class="line">    <span class="keyword">while</span> (curNode != <span class="keyword">null</span>) &#123;</span><br><span class="line">        map.get(curNode).next = map.get(curNode.next);</span><br><span class="line">        map.get(curNode).random = map.get(curNode.random);</span><br><span class="line">        curNode = curNode.next;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> map.get(head);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h1 id="3-栈和队列">3、栈和队列</h1>
<ul>
<li>熟悉栈的使用场景
<ul>
<li>后入先出，保存临时值</li>
<li>利用栈DFS深度搜索</li>
</ul>
</li>
<li>熟悉队列的使用场景
<ul>
<li>利用队列BFS广度搜索</li>
</ul>
</li>
</ul>
<h2 id="155-最小栈">155. 最小栈</h2>
<p><a href="https://leetcode-cn.com/problems/min-stack/" target="_blank" rel="noopener">最小栈</a></p>
<p>用链表来模拟队列，栈顶元素为链表头</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MinStack</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/** initialize your data structure here. */</span></span><br><span class="line">    <span class="comment">// 用链表来模拟队列，栈顶元素为链表头</span></span><br><span class="line">    <span class="keyword">private</span> Node head;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">MinStack</span><span class="params">()</span> </span>&#123;&#125;</span><br><span class="line">    </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">push</span><span class="params">(<span class="keyword">int</span> x)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (head == <span class="keyword">null</span>) &#123;</span><br><span class="line">            head = <span class="keyword">new</span> Node(x, x);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            head = <span class="keyword">new</span> Node(x, Math.min(x, head.min), head);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">pop</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        head = head.next;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">top</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> head.val;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getMin</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> head.min;</span><br><span class="line">    &#125;</span><br><span class="line">        <span class="class"><span class="keyword">class</span> <span class="title">Node</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> val;</span><br><span class="line">        <span class="keyword">int</span> min;</span><br><span class="line">        Node next;</span><br><span class="line">        Node(<span class="keyword">int</span> val, <span class="keyword">int</span> min) &#123;</span><br><span class="line">            <span class="keyword">this</span>.val = val;</span><br><span class="line">            <span class="keyword">this</span>.min = min;</span><br><span class="line">            <span class="keyword">this</span>.next = <span class="keyword">null</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        Node(<span class="keyword">int</span> val, <span class="keyword">int</span> min, Node next) &#123;</span><br><span class="line">            <span class="keyword">this</span>.val = val;</span><br><span class="line">            <span class="keyword">this</span>.min = min;</span><br><span class="line">            <span class="keyword">this</span>.next = next;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="150-逆波兰表达式求值">150. 逆波兰表达式求值</h2>
<p><a href="https://leetcode-cn.com/problems/evaluate-reverse-polish-notation/" target="_blank" rel="noopener">逆波兰表达式求值</a></p>
<blockquote>
<p>输入: [“2”, “1”, “+”, “3”, “*”]<br>
输出: 9<br>
解释: 该算式转化为常见的中缀算术表达式为：((2 + 1) * 3) = 9</p>
</blockquote>
<p><strong>思路：</strong><br>
通过栈保存原来的元素，遇到表达式弹出运算，再推入结果，重复这个过程</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">evalRPN</span><span class="params">(String[] tokens)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> left, right;<span class="comment">//left放左操作数，right放右操作数</span></span><br><span class="line">        <span class="comment">//依次遍历逆波兰式字符串，数字进栈，运算符，从栈中弹俩次</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; tokens.length; i++) &#123;</span><br><span class="line">            String str = tokens[i];</span><br><span class="line">            <span class="comment">//按照*/+-的优先级顺序</span></span><br><span class="line">            <span class="keyword">if</span> (str.equals(<span class="string">"*"</span>)) &#123;</span><br><span class="line">                right = stack.pop();</span><br><span class="line">                left = stack.pop();</span><br><span class="line">                stack.push(left * right);<span class="comment">//新运算数入栈</span></span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (str.equals(<span class="string">"/"</span>)) &#123;</span><br><span class="line">                right = stack.pop();</span><br><span class="line">                left = stack.pop();</span><br><span class="line">                stack.push(left / right);<span class="comment">//新操作数入栈</span></span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (str.equals(<span class="string">"+"</span>)) &#123;</span><br><span class="line">                right = stack.pop();</span><br><span class="line">                left = stack.pop();</span><br><span class="line">                stack.push(left + right);<span class="comment">//新操作数入栈</span></span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (str.equals(<span class="string">"-"</span>)) &#123;</span><br><span class="line">                right = stack.pop();</span><br><span class="line">                left = stack.pop();</span><br><span class="line">                stack.push(left - right);<span class="comment">//新操作数入栈</span></span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                stack.push(Integer.valueOf(str));</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> stack.pop();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="394-字符串解码">394. 字符串解码</h2>
<p><a href="https://leetcode-cn.com/problems/decode-string/" target="_blank" rel="noopener">字符串解码</a></p>
<p><strong>辅助栈，双栈</strong></p>
<p>遇到左括号将数字存数字存到数字栈，字符串存到字符串栈，保存信息；遇到右括号数字栈取出数字 <code>k</code> ，重复复制当前的子字符串 <code>k</code> 次，再与字符串栈中的字符串合并。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">decodeString</span><span class="params">(String s)</span> </span>&#123;</span><br><span class="line">        Stack&lt;Integer&gt; stackMulti = <span class="keyword">new</span> Stack&lt;Integer&gt;();</span><br><span class="line">        Stack&lt;String&gt; stackStr = <span class="keyword">new</span> Stack&lt;String&gt;();</span><br><span class="line">        <span class="keyword">int</span> multi = <span class="number">0</span>;</span><br><span class="line">        String res = <span class="keyword">new</span> String();</span><br><span class="line">        <span class="keyword">for</span> (Character c : s.toCharArray()) &#123;</span><br><span class="line">            <span class="keyword">if</span> (c == <span class="string">'['</span>) &#123;</span><br><span class="line">                <span class="comment">// 左括号，将左括号左边的字符串存到字符串栈，把数字存到数字栈</span></span><br><span class="line">                stackMulti.push(multi);</span><br><span class="line">                stackStr.push(res);</span><br><span class="line">                multi = <span class="number">0</span>;</span><br><span class="line">                res = <span class="keyword">new</span> String();</span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (c == <span class="string">']'</span>) &#123;</span><br><span class="line">                <span class="comment">// 右括号，数字栈取出一个数字k，重复当前子字符串k次，完成本轮解码</span></span><br><span class="line">                <span class="comment">// 并于之前的子字符串合并，如"3[a2[c]]"，比如本轮是完成"2[c]"</span></span><br><span class="line">                <span class="comment">// 那么于之前的子字符串合并后就是"acc"</span></span><br><span class="line">                <span class="keyword">int</span> k = stackMulti.pop();</span><br><span class="line">                String tempStr = <span class="keyword">new</span> String();</span><br><span class="line">                <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; k; i++) &#123;</span><br><span class="line">                    tempStr += res;</span><br><span class="line">                &#125;</span><br><span class="line">                res = stackStr.pop() + tempStr;</span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (Character.isDigit(c)) &#123;</span><br><span class="line">                multi = multi * <span class="number">10</span> + Integer.parseInt(c + <span class="string">""</span>);</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                res += c;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> res;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="94-二叉树的中序遍历">94. 二叉树的中序遍历</h2>
<p><a href="https://leetcode-cn.com/problems/binary-tree-inorder-traversal/" target="_blank" rel="noopener">二叉树的中序遍历</a></p>
<p><strong>利用栈实现</strong> ，先找到二叉树的最左叶子节点对其访问，然后退回上一个节点访问，如果有右子树则对其右子树同样地进行找到最左叶子节点操作。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> List&lt;Integer&gt; <span class="title">inorderTraversal</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">        List&lt;Integer&gt; output = <span class="keyword">new</span> LinkedList&lt;Integer&gt;();</span><br><span class="line">        Stack&lt;TreeNode&gt; stack = <span class="keyword">new</span> Stack&lt;TreeNode&gt;();</span><br><span class="line">        TreeNode tempNode = root;</span><br><span class="line">        <span class="keyword">while</span> (tempNode != <span class="keyword">null</span> || !stack.isEmpty()) &#123;</span><br><span class="line">            <span class="keyword">while</span> (tempNode != <span class="keyword">null</span>) &#123;</span><br><span class="line">                stack.push(tempNode);</span><br><span class="line">                tempNode = tempNode.left;</span><br><span class="line">            &#125;</span><br><span class="line">            tempNode = stack.pop();</span><br><span class="line">            output.add(tempNode.val);</span><br><span class="line">            tempNode = tempNode.right;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> output;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="133-克隆图">133. 克隆图</h2>
<p><a href="https://leetcode-cn.com/problems/clone-graph/" target="_blank" rel="noopener">克隆图</a></p>
<blockquote>
<p>给你无向连通图中一个节点的引用，请你返回该图的深拷贝（克隆）。</p>
</blockquote>
<p>和138. 复制带随机指针的链表同理，利用hashMap保存克隆出来的节点，通过遍历的方式进行复制。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> HashMap &lt;Node, Node&gt; visited = <span class="keyword">new</span> HashMap &lt;&gt; ();</span><br><span class="line">    <span class="function"><span class="keyword">public</span> Node <span class="title">cloneGraph</span><span class="params">(Node node)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (node == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> node;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 如果该节点已经被访问过了，则直接从哈希表中取出对应的克隆节点返回</span></span><br><span class="line">        <span class="keyword">if</span> (visited.containsKey(node)) &#123;</span><br><span class="line">            <span class="keyword">return</span> visited.get(node);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 克隆节点，注意到为了深拷贝我们不会克隆它的邻居的列表</span></span><br><span class="line">        Node cloneNode = <span class="keyword">new</span> Node(node.val, <span class="keyword">new</span> ArrayList());</span><br><span class="line">        <span class="comment">// 哈希表存储</span></span><br><span class="line">        visited.put(node, cloneNode);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 遍历该节点的邻居并更新克隆节点的邻居列表</span></span><br><span class="line">        <span class="keyword">for</span> (Node neighbor: node.neighbors) &#123;</span><br><span class="line">            cloneNode.neighbors.add(cloneGraph(neighbor));</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> cloneNode;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="200-岛屿数量岛屿类问题通解">200. 岛屿数量（岛屿类问题通解）</h2>
<p><a href="https://leetcode-cn.com/problems/number-of-islands/" target="_blank" rel="noopener">岛屿数量</a></p>
<blockquote>
<p>给你一个由 <code>'1'</code>（陆地）和 <code>'0'</code>（水）组成的的二维网格，请你计算网格中岛屿的数量。</p>
</blockquote>
<p><strong>代码</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">numIslands</span><span class="params">(<span class="keyword">char</span>[][] grid)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> numIslands = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> r = <span class="number">0</span>; r &lt; grid.length; r++) &#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> c = <span class="number">0</span>; c &lt; grid[<span class="number">0</span>].length; c++) &#123;</span><br><span class="line">                <span class="keyword">if</span> (grid[r][c] == <span class="string">'1'</span>) &#123;</span><br><span class="line">                    numIslands++;</span><br><span class="line">                    dfs(grid, r, c);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> numIslands;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">dfs</span><span class="params">(<span class="keyword">char</span>[][] grid, <span class="keyword">int</span> r, <span class="keyword">int</span> c)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// base case</span></span><br><span class="line">        <span class="keyword">if</span> (!inArea(grid, r, c)) &#123;</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 如果不是岛屿</span></span><br><span class="line">        <span class="keyword">if</span> (grid[r][c] != <span class="string">'1'</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 标记已经遍历过</span></span><br><span class="line">        grid[r][c] = <span class="string">'2'</span>;</span><br><span class="line"></span><br><span class="line">        dfs(grid, r + <span class="number">1</span>, c);</span><br><span class="line">        dfs(grid, r - <span class="number">1</span>, c);</span><br><span class="line">        dfs(grid, r, c + <span class="number">1</span>);</span><br><span class="line">        dfs(grid, r, c - <span class="number">1</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">boolean</span> <span class="title">inArea</span><span class="params">(<span class="keyword">char</span>[][] grid, <span class="keyword">int</span> r, <span class="keyword">int</span> c)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span> &lt;= r &amp;&amp; r &lt; grid.length &amp;&amp; <span class="number">0</span> &lt;= c &amp;&amp; c &lt; grid[<span class="number">0</span>].length;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>岛屿类问题代码模板：</strong> <a href="https://leetcode-cn.com/problems/number-of-islands/solution/dao-yu-lei-wen-ti-de-tong-yong-jie-fa-dfs-bian-li-/" target="_blank" rel="noopener">参考链接</a></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">dfs</span><span class="params">(<span class="keyword">int</span>[][] grid, <span class="keyword">int</span> r, <span class="keyword">int</span> c)</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 判断 base case</span></span><br><span class="line">    <span class="keyword">if</span> (!inArea(grid, r, c)) &#123;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 如果这个格子不是岛屿，直接返回</span></span><br><span class="line">    <span class="keyword">if</span> (grid[r][c] != <span class="number">1</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    grid[r][c] = <span class="number">2</span>; <span class="comment">// 将格子标记为「已遍历过」</span></span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 访问上、下、左、右四个相邻结点</span></span><br><span class="line">    dfs(grid, r - <span class="number">1</span>, c);</span><br><span class="line">    dfs(grid, r + <span class="number">1</span>, c);</span><br><span class="line">    dfs(grid, r, c - <span class="number">1</span>);</span><br><span class="line">    dfs(grid, r, c + <span class="number">1</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 判断坐标 (r, c) 是否在网格中</span></span><br><span class="line"><span class="function"><span class="keyword">boolean</span> <span class="title">inArea</span><span class="params">(<span class="keyword">int</span>[][] grid, <span class="keyword">int</span> r, <span class="keyword">int</span> c)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span> &lt;= r &amp;&amp; r &lt; grid.length </span><br><span class="line">        	&amp;&amp; <span class="number">0</span> &lt;= c &amp;&amp; c &lt; grid[<span class="number">0</span>].length;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="84-柱状图中最大的矩形单调栈">84. 柱状图中最大的矩形（单调栈）</h2>
<p><a href="https://leetcode-cn.com/problems/largest-rectangle-in-histogram/" target="_blank" rel="noopener">柱状图中最大的矩形</a></p>
<blockquote>
<p>给定 <em>n</em> 个非负整数，用来表示柱状图中各个柱子的高度。每个柱子彼此相邻，且宽度为 1 。求在该柱状图中，能够勾勒出来的矩形的最大面积。</p>
</blockquote>
<p><strong>暴力：</strong> 遍历数组，以当前 <code>heights[i]</code> 为高度从左往右寻找连续的高度大于等于 <code>heights[i]</code> 的序列，计算其面积并与 <code>maxArea</code> 比较，更新 <code>maxArea</code>。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">largestRectangleArea</span><span class="params">(<span class="keyword">int</span>[] heights)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> maxArea = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; heights.length; i++) &#123;</span><br><span class="line">            <span class="keyword">int</span> width = <span class="number">1</span>;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> j = i + <span class="number">1</span>; j &lt; heights.length; j++) &#123;</span><br><span class="line">                <span class="keyword">if</span> (heights[j] &gt;= heights[i]) &#123;</span><br><span class="line">                    width++;</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> j = i - <span class="number">1</span>; j &gt;= <span class="number">0</span>; j--) &#123;</span><br><span class="line">                <span class="keyword">if</span> (heights[j] &gt;= heights[i]) &#123;</span><br><span class="line">                    width++;</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (heights[i] * width &gt; maxArea) &#123;</span><br><span class="line">                maxArea = heights[i] * width;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> maxArea;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>单调栈：</strong> <a href="https://blog.csdn.net/Zolewit/article/details/88863970" target="_blank" rel="noopener">参考1</a>、<a href="https://leetcode-cn.com/problems/largest-rectangle-in-histogram/solution/xiang-jie-dan-diao-zhan-bi-xu-miao-dong-by-sweetie/" target="_blank" rel="noopener">参考2</a></p>
<p>维护一个单调增栈，为了便于计算面积，在原始数组的前后都添加一个0高度的柱子。</p>
<p>当第 <code>i</code> 个柱子进栈时，如果栈顶柱子（标记为 <code>A</code> ）的高度低于或等于第 <code>i</code> 个柱子，则第 <code>i</code> 个柱子进栈；如果高于第 <code>i</code> 个柱子，则出栈，并计算以柱子 <code>A</code> 为高的矩形最大面积。</p>
<ul>
<li>高度 <code>height</code>：柱子 <code>A</code> 的高度；</li>
<li>右边沿：正好是 <code>i</code> ，由于单调栈的性质，第 <code>i</code> 个柱子就是右边第一个矮于 <code>A</code> 的柱子；</li>
<li>左边沿：单调栈中紧邻 <code>A</code> 的柱子（如果 <code>A</code> 已经出栈，那么左边沿就是 <code>A</code> 出栈后的栈顶）；</li>
<li>宽度 <code>width</code>：<code>右边沿 - 左边沿 - 1​</code> 。</li>
</ul>
<p>因此每次出栈后去更新矩形最大面积 <code>maxArea = Math.max(maxArea, height * width);</code> ，代码如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">largestRectangleArea</span><span class="params">(<span class="keyword">int</span>[] heights)</span> </span>&#123;</span><br><span class="line">        Stack&lt;Integer&gt; monotonicalStack = <span class="keyword">new</span> Stack&lt;Integer&gt;();</span><br><span class="line">        <span class="keyword">int</span> maxArea = <span class="number">0</span>;</span><br><span class="line">        <span class="comment">// 原始数组前后添加高度为0的柱子</span></span><br><span class="line">        <span class="keyword">int</span>[] newHeights = <span class="keyword">new</span> <span class="keyword">int</span>[heights.length + <span class="number">2</span>];</span><br><span class="line">        newHeights[<span class="number">0</span>] = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; heights.length; i++) &#123;</span><br><span class="line">            newHeights[i + <span class="number">1</span>] = heights[i];</span><br><span class="line">        &#125;</span><br><span class="line">        newHeights[heights.length + <span class="number">1</span>] = <span class="number">0</span>;</span><br><span class="line">        <span class="comment">// 维护单调栈</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; newHeights.length; i++) &#123;</span><br><span class="line">            <span class="keyword">while</span> (!monotonicalStack.isEmpty() &amp;&amp; newHeights[i] &lt; newHeights[monotonicalStack.peek()]) &#123;</span><br><span class="line">                <span class="keyword">int</span> height = newHeights[monotonicalStack.pop()];</span><br><span class="line">                <span class="keyword">int</span> width = i - monotonicalStack.peek() - <span class="number">1</span>;</span><br><span class="line">                maxArea = Math.max(maxArea, height * width);</span><br><span class="line">            &#125;</span><br><span class="line">            monotonicalStack.push(i);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> maxArea;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="232-用栈实现队列">232. 用栈实现队列</h2>
<p><a href="https://leetcode-cn.com/problems/implement-queue-using-stacks/" target="_blank" rel="noopener">用栈实现队列</a></p>
<blockquote>
<p>请你仅使用两个栈实现先入先出队列。队列应当支持一般队列的支持的所有操作（<code>push</code>、<code>pop</code>、<code>peek</code>、<code>empty</code>）。</p>
</blockquote>
<p>创建两个栈，栈A作为输入栈，栈B作为输出栈，用栈A和栈B实现先入先出队列。假设一组升序序列进入队列中，栈A中的元素从栈顶到栈底时逆序的，栈B中的元素从栈顶到栈底时正序的。（可以自己画图理解）</p>
<ul>
<li>入队 <code>push</code>：直接压入栈A；</li>
<li>出队 <code>pop</code>：如果栈B为空，那么将栈A全部弹出压入栈B中，然后栈 <code>B.pop()</code>；如果栈B不为空，直接栈 <code>B.pop()</code>；</li>
<li>队列顶端元素 <code>peek</code>：如果栈B为空，那么将栈A全部弹出压入栈B中，然后栈 <code>B.peek()</code>；如果栈B不为空，直接栈 <code>B.peek()</code>；</li>
<li>队列是否为空 <code>empty</code>：当栈A和栈B都为空时，队列为空。</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyQueue</span> </span>&#123;</span><br><span class="line">    Stack&lt;Integer&gt; stackA; <span class="comment">// 输入栈</span></span><br><span class="line">    Stack&lt;Integer&gt; stackB; <span class="comment">// 输出栈</span></span><br><span class="line">    </span><br><span class="line">    <span class="comment">/** Initialize your data structure here. */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">MyQueue</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        stackA = <span class="keyword">new</span> Stack&lt;Integer&gt;();</span><br><span class="line">        stackB = <span class="keyword">new</span> Stack&lt;Integer&gt;();</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">/** Push element x to the back of queue. */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">push</span><span class="params">(<span class="keyword">int</span> x)</span> </span>&#123;</span><br><span class="line">        stackA.push(x);</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">/** Removes the element from in front of queue and returns that element. */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">pop</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 如果b栈为空，则将a栈全部弹出并压入b栈中，然后b.pop()</span></span><br><span class="line">        <span class="keyword">if</span> (stackB.isEmpty()) &#123;</span><br><span class="line">            <span class="keyword">while</span> (!stackA.isEmpty()) &#123;</span><br><span class="line">                stackB.push(stackA.pop());</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> stackB.pop();</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">/** Get the front element. */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">peek</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (stackB.isEmpty()) &#123;</span><br><span class="line">            <span class="keyword">while</span>(!stackA.isEmpty()) &#123;</span><br><span class="line">                stackB.push(stackA.pop());</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> stackB.peek();</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">/** Returns whether the queue is empty. */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">empty</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> stackA.isEmpty() &amp;&amp; stackB.isEmpty();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="542-01-矩阵多源bfs问题">542. 01 矩阵（多源BFS问题）</h2>
<p><a href="https://leetcode-cn.com/problems/01-matrix/" target="_blank" rel="noopener">01 矩阵</a></p>
<blockquote>
<p>给定一个由 0 和 1 组成的矩阵，找出每个元素到最近的 0 的距离。</p>
</blockquote>
<p>寻找到最近的 <code>0</code> 的距离，转换到每个 <code>0</code> 元素到周围 <code>1</code> 的距离问题。</p>
<p><strong>多源BFS：</strong> 首先把每个 <code>0</code> 入队，向周围扩散寻找 <code>1</code>，找到后记录走过的距离。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">int</span>[][] updateMatrix(<span class="keyword">int</span>[][] matrix) &#123;</span><br><span class="line">        <span class="comment">// 上下左右</span></span><br><span class="line">        <span class="keyword">int</span>[][] direction = &#123;&#123;<span class="number">1</span>, <span class="number">0</span>&#125;, &#123;-<span class="number">1</span>, <span class="number">0</span>&#125;, &#123;<span class="number">0</span>, -<span class="number">1</span>&#125;, &#123;<span class="number">0</span>, <span class="number">1</span>&#125;&#125;;</span><br><span class="line">        <span class="keyword">int</span> m = matrix.length, n = matrix[<span class="number">0</span>].length;</span><br><span class="line">        <span class="comment">// 首先将所有的 0 都入队，并且将 0 的位置设置成true，表示该位置是被访问过的</span></span><br><span class="line">        <span class="keyword">boolean</span>[][] visited = <span class="keyword">new</span> <span class="keyword">boolean</span>[m][n];</span><br><span class="line">        Queue&lt;<span class="keyword">int</span>[]&gt; queue = <span class="keyword">new</span> LinkedList&lt;<span class="keyword">int</span>[]&gt;();</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; m; i++) &#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">0</span>; j &lt; n; j++) &#123;</span><br><span class="line">                <span class="keyword">if</span> (matrix[i][j] == <span class="number">0</span>) &#123;</span><br><span class="line">                    visited[i][j] = <span class="keyword">true</span>;</span><br><span class="line">                    queue.offer(<span class="keyword">new</span> <span class="keyword">int</span>[] &#123;i, j&#125;);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">		<span class="comment">// BFS</span></span><br><span class="line">        <span class="keyword">int</span> distance = <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">while</span> (!queue.isEmpty()) &#123;</span><br><span class="line">            <span class="keyword">int</span> count = queue.size();</span><br><span class="line">            <span class="keyword">while</span> (count &gt; <span class="number">0</span>) &#123;</span><br><span class="line">                <span class="keyword">int</span>[] temp = queue.poll();</span><br><span class="line">                <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">4</span>; i++) &#123;</span><br><span class="line">                    <span class="keyword">int</span> x = temp[<span class="number">0</span>] + direction[i][<span class="number">0</span>];</span><br><span class="line">                    <span class="keyword">int</span> y = temp[<span class="number">1</span>] + direction[i][<span class="number">1</span>];</span><br><span class="line">                    <span class="keyword">if</span> (<span class="number">0</span> &lt;= x &amp;&amp; x &lt; m &amp;&amp; <span class="number">0</span> &lt;= y &amp;&amp; y &lt; n &amp;&amp; !visited[x][y]) &#123;</span><br><span class="line">                        matrix[x][y] = distance;</span><br><span class="line">                        visited[x][y] = <span class="keyword">true</span>;</span><br><span class="line">                        queue.offer(<span class="keyword">new</span> <span class="keyword">int</span>[] &#123;x, y&#125;);</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">                count--;</span><br><span class="line">            &#125;</span><br><span class="line">            distance++;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> matrix;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h1 id="4-二进制">4、二进制</h1>
<h2 id="常见二进制操作">常见二进制操作</h2>
<p><strong>异或 ^</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">a = <span class="number">0</span> ^ a = a ^ <span class="number">0</span></span><br><span class="line"><span class="number">0</span> = a ^ a</span><br></pre></td></tr></table></figure>
<p>由上可以推导出： <code>a = a ^ b ^ b</code> ，即相等的两个数异或值为0。</p>
<p><strong>交换两个数</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">a = a ^ b</span><br><span class="line">b = a ^ b</span><br><span class="line">a = a ^ b</span><br></pre></td></tr></table></figure>
<p><strong>按位与 &amp;</strong></p>
<p><strong>移除最后一个1</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">a = n &amp; (n - <span class="number">1</span>)</span><br></pre></td></tr></table></figure>
<p><strong>获取最后一个1</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">diff = (n &amp; (n - <span class="number">1</span>)) ^ n</span><br></pre></td></tr></table></figure>
<h2 id="136-只出现一次的数字">136. 只出现一次的数字</h2>
<p><a href="https://leetcode-cn.com/problems/single-number/" target="_blank" rel="noopener">只出现一次的数字</a></p>
<blockquote>
<p>给定一个<strong>非空</strong>整数数组，除了某个元素只出现一次以外，其余每个元素均出现两次。找出那个只出现了一次的元素。</p>
</blockquote>
<p>利用位运算的异或操作，两个相同的数字异或结果是0。因为整个数组只有一个元素只出现了一次，那么对整个数组进行异或操作，最后的答案就是只出现了一次的那个元素。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">singleNumber</span><span class="params">(<span class="keyword">int</span>[] nums)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> res = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> num : nums) &#123;</span><br><span class="line">            res = res ^ num;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> res;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="137-只出现一次的数字-ii">137. 只出现一次的数字 II</h2>
<p><a href="https://leetcode-cn.com/problems/single-number-ii/" target="_blank" rel="noopener">只出现一次的数字 II</a></p>
<blockquote>
<p>给定一个<strong>非空</strong>整数数组，除了某个元素只出现一次以外，其余每个元素均出现了三次。找出那个只出现了一次的元素。</p>
</blockquote>
<p><strong>按位求和</strong></p>
<p>图片取自leetcode，把数的二进制每一位相加，然后对其每一位的和取余。</p>
<p><img src="https://pic.tyzhang.top/images/2020/12/10/1607143013-YeZWjn-file_1607143013476.png" alt="1607143013-YeZWjn-file_1607143013476.png"></p>
<p>其他数字都出现了 <code>3</code> 次，只有目标数出现 <code>1</code> 次，那么每一位的 <code>1</code>的个数无非两种情况：</p>
<ul>
<li>为 <code>3</code> 的倍数（全为出现3次的数）</li>
<li><code>3</code> 的倍数 <code>+1</code>（包含出现一次的数）</li>
</ul>
<p>这个 <code>3</code> 的倍数 <code>+1</code> 的情况就是我们目标数所在的那一位。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">singleNumber</span><span class="params">(<span class="keyword">int</span>[] nums)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> res = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">32</span>; i++) &#123;</span><br><span class="line">            <span class="keyword">int</span> count = <span class="number">0</span>;</span><br><span class="line">            <span class="comment">// 统计第 i 位是 1 的数字的个数</span></span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> num : nums) &#123;</span><br><span class="line">                <span class="keyword">if</span> ((num &gt;&gt; i &amp; <span class="number">0x01</span>) == <span class="number">0x01</span>) &#123;</span><br><span class="line">                    count++;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">// 当取余为 1 的情况时，说明目标数在该位有 1</span></span><br><span class="line">            <span class="keyword">if</span> (count % <span class="number">3</span> == <span class="number">1</span>) &#123;</span><br><span class="line">                res |= <span class="number">1</span> &lt;&lt; i;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> res;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong><a href="https://zbsong.top/article/%E5%8D%A1%E8%AF%BA%E5%9B%BE%E4%B8%8E%E2%80%9C%E5%8F%AA%E5%87%BA%E7%8E%B0%E4%B8%80%E6%AC%A1%E7%9A%84%E6%95%B0%E5%AD%97%E2%80%9D%E9%97%AE%E9%A2%98/">位运算——卡诺图</a></strong></p>
<p>如果能设计一个状态转换电路，使得一个数出现 <code>3</code> 次时能自动抵消为 <code>0</code>，最后剩下的就是只出现 <code>1</code> 次的数。</p>
<p>列出状态转移矩阵，由于无法直接观察得出所需执行操作的具体形式，画出卡诺图确定转移方程。</p>
<p><strong><a href="https://zbsong.top/article/%E5%8D%A1%E8%AF%BA%E5%9B%BE%E4%B8%8E%E2%80%9C%E5%8F%AA%E5%87%BA%E7%8E%B0%E4%B8%80%E6%AC%A1%E7%9A%84%E6%95%B0%E5%AD%97%E2%80%9D%E9%97%AE%E9%A2%98/">位运算——真值表达式</a></strong></p>
<p>列出真值表，写出所需的真值表达式。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">singleNumber</span><span class="params">(<span class="keyword">int</span>[] nums)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> a = <span class="number">0</span>, b = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> x : nums) &#123;</span><br><span class="line">            b = ~a &amp; (x ^ b);</span><br><span class="line">            a = ~b &amp; (x ^ a);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> b;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="260-只出现一次的数字-iii">260. 只出现一次的数字 III</h2>
<p><a href="https://leetcode-cn.com/problems/single-number-iii/" target="_blank" rel="noopener">只出现一次的数字 III</a></p>
<blockquote>
<p>给定一个整数数组 <code>nums</code>，其中恰好有两个元素只出现一次，其余所有元素均出现两次。 找出只出现一次的那两个元素。</p>
</blockquote>
<p>建立一个值到频率的映射关系的哈希表，返回频率为 1 的数字。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">  <span class="keyword">public</span> <span class="keyword">int</span>[] singleNumber(<span class="keyword">int</span>[] nums) &#123;</span><br><span class="line">    Map&lt;Integer, Integer&gt; hashmap = <span class="keyword">new</span> HashMap();</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">int</span> n : nums)</span><br><span class="line">      hashmap.put(n, hashmap.getOrDefault(n, <span class="number">0</span>) + <span class="number">1</span>);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">int</span>[] output = <span class="keyword">new</span> <span class="keyword">int</span>[<span class="number">2</span>];</span><br><span class="line">    <span class="keyword">int</span> idx = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span> (Map.Entry&lt;Integer, Integer&gt; item : hashmap.entrySet())</span><br><span class="line">      <span class="keyword">if</span> (item.getValue() == <span class="number">1</span>) output[idx++] = item.getKey();</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> output;</span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure>
<p><strong>解法2</strong></p>
<p>将问题转换成为“有一个数组每个数字都出现两次，有一个数字只出现了一次，求出该数字”。</p>
<p>将所有数字分成两组，使得：</p>
<ol>
<li>两个只出现一次的数字在不同的组中</li>
<li>相同的数字会被分到相同的组中</li>
</ol>
<p>记两个只出现了一次的数字为 a 和 b，那么所有数字异或的结果 xor 就等于 a 和 b 异或的结果。</p>
<p>我们知道，异或运算相同的两个数结果为 0，那么取 xor 的最后一个 1 （记 <code>mask = xor ^ (xor &amp; (xor - 1))</code>，它表示数字 a 和 b 在这一位上一定不相同，据此我们就可以把所有数字分成两组。</p>
<ul>
<li>在 xor 的最后一个 1 上边，表示 a 和 b 在该位上不相等，那么可以根据这个点将 a 和 b 分到不同组中</li>
<li>两个相同的数字的对应位都应该是相同的，一个被分到了某个组，另一个必然也被分到这一组</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">int</span>[] singleNumber(<span class="keyword">int</span>[] nums) &#123;</span><br><span class="line">        <span class="keyword">int</span> xor = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> n : nums) &#123;</span><br><span class="line">            xor ^= n;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">int</span> mask = xor ^ (xor &amp; (xor - <span class="number">1</span>));</span><br><span class="line">        <span class="keyword">int</span>[] result = <span class="keyword">new</span> <span class="keyword">int</span>[<span class="number">2</span>];</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> n : nums) &#123;</span><br><span class="line">            <span class="keyword">if</span> ((mask &amp; n) == <span class="number">0</span>) &#123;</span><br><span class="line">                result[<span class="number">0</span>] ^= n;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                result[<span class="number">1</span>] ^= n;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="191-位1的个数">191. 位1的个数</h2>
<p><a href="https://leetcode-cn.com/problems/number-of-1-bits/" target="_blank" rel="noopener">位1的个数</a></p>
<blockquote>
<p>编写一个函数，输入是一个无符号整数（以二进制串的形式），返回其二进制表达式中数字位数为 ‘1’ 的个数（也被称为<a href="https://baike.baidu.com/item/%E6%B1%89%E6%98%8E%E9%87%8D%E9%87%8F" target="_blank" rel="noopener">汉明重量</a>）。java 没有无符号整数类型。</p>
</blockquote>
<p><strong>掩码</strong> ，利用掩码挨位判断是否为 1。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="comment">// you need to treat n as an unsigned value</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">hammingWeight</span><span class="params">(<span class="keyword">int</span> n)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> num = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">int</span> mask = <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">32</span>; i++) &#123;</span><br><span class="line">            <span class="keyword">if</span> ((n &amp; mask &lt;&lt; i) != <span class="number">0</span>) &#123;</span><br><span class="line">                num++;</span><br><span class="line">                System.out.println(n &amp; mask &lt;&lt; i);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> num;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>获取最后一个1</strong></p>
<p>利用 <code>n &amp; (n-1)</code> 反转 n 的最后一个 1。</p>
<p>假设  <code>n = 0110</code> 那么 <code>n - 1 = 0101</code>，此时 <code>n &amp; (n-1) = 0100</code>，可以看到成功抹掉了最后一个 1。那么我们重复这个过程，直到 <code>n = 0</code> 停止，统计重复了多少次即可得出 n 有多少个 1。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="comment">// you need to treat n as an unsigned value</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">hammingWeight</span><span class="params">(<span class="keyword">int</span> n)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> num = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">while</span> (n != <span class="number">0</span>) &#123;</span><br><span class="line">            num++;</span><br><span class="line">            n = n &amp; (n-<span class="number">1</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> num;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="338-比特位计数">338. 比特位计数</h2>
<p><a href="https://leetcode-cn.com/problems/counting-bits/" target="_blank" rel="noopener">比特位计数</a></p>
<blockquote>
<p>给定一个非负整数 <strong>num</strong>。对于 <strong>0 ≤ i ≤ num</strong> 范围中的每个数字 <strong>i</strong> ，计算其二进制数中的 1 的数目并将它们作为数组返回。</p>
</blockquote>
<p>可以看作是 191 的续，对每个数字都求一次就行。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">int</span>[] countBits(<span class="keyword">int</span> num) &#123;</span><br><span class="line">        <span class="keyword">int</span>[] res = <span class="keyword">new</span> <span class="keyword">int</span>[num + <span class="number">1</span>];</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; num + <span class="number">1</span>; i++) &#123;</span><br><span class="line">            res[i] = hammingWeight(i);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> res;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">hammingWeight</span><span class="params">(<span class="keyword">int</span> n)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> num = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">while</span> (n != <span class="number">0</span>) &#123;</span><br><span class="line">            num++;</span><br><span class="line">            n = n &amp; (n - <span class="number">1</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> num;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>动态规划</strong> 待完善</p>
<h2 id="190-颠倒二进制位">190. 颠倒二进制位</h2>
<p><a href="https://leetcode-cn.com/problems/reverse-bits/" target="_blank" rel="noopener">颠倒二进制位</a></p>
<blockquote>
<p>颠倒给定的 32 位无符号整数的二进制位。</p>
</blockquote>
<p>用一个变量 <code>res</code> 去存储结果，依次得到要转换数字的低位，然后依次保存到 <code>res</code> 中。<code>res</code> 每得到一位后进行左移腾出位置保存下一位。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="comment">// you need treat n as an unsigned value</span></span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">reverseBits</span><span class="params">(<span class="keyword">int</span> n)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> res = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">int</span> count = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">while</span> (count &lt; <span class="number">32</span>) &#123;</span><br><span class="line">            res &lt;&lt;= <span class="number">1</span>;  <span class="comment">//res 左移一位空出位置</span></span><br><span class="line">            res |= (n &amp; <span class="number">1</span>); <span class="comment">//得到的最低位加过来</span></span><br><span class="line">            n &gt;&gt;= <span class="number">1</span>;<span class="comment">//原数字右移一位去掉已经处理过的最低位</span></span><br><span class="line">            count++;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> res;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>分治</strong></p>
<p>我们知道逆序一组数字 <code>1,2,3,4</code>，可以先 <code>1,2</code>  为 <code>2,1</code>，<code>3,4</code> 逆序为 <code>4,3</code> 得到 <code>2,1,4,3</code>，然后再把 <code>2,1</code> 和 <code>3,4</code> 逆序，得到原序列的逆序 <code>4,3,2,1</code>。</p>
<p>32位的二进制位也是同理，可以被分为如下图所示的顺序：</p>
<p><img src="https://pic.tyzhang.top/images/2020/12/17/image.png" alt="image.png"></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="comment">// you need treat n as an unsigned value</span></span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">reverseBits</span><span class="params">(<span class="keyword">int</span> n)</span> </span>&#123;</span><br><span class="line">        n = (n &gt;&gt;&gt; <span class="number">16</span>) | (n &lt;&lt; <span class="number">16</span>);</span><br><span class="line">        n = ((n &amp; <span class="number">0xff00ff00</span>) &gt;&gt;&gt; <span class="number">8</span>) | ((n &amp; <span class="number">0x00ff00ff</span>) &lt;&lt; <span class="number">8</span>);</span><br><span class="line">        n = ((n &amp; <span class="number">0xf0f0f0f0</span>) &gt;&gt;&gt; <span class="number">4</span>) | ((n &amp; <span class="number">0x0f0f0f0f</span>) &lt;&lt; <span class="number">4</span>);</span><br><span class="line">        n = ((n &amp; <span class="number">0xcccccccc</span>) &gt;&gt;&gt; <span class="number">2</span>) | ((n &amp; <span class="number">0x33333333</span>) &lt;&lt; <span class="number">2</span>);</span><br><span class="line">        n = ((n &amp; <span class="number">0xaaaaaaaa</span>) &gt;&gt;&gt; <span class="number">1</span>) | ((n &amp; <span class="number">0x55555555</span>) &lt;&lt; <span class="number">1</span>);</span><br><span class="line">        <span class="keyword">return</span> n;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>Integer自带的reverse函数</strong>  ，具体可以看<a href="https://www.jianshu.com/p/be272c8704d9" target="_blank" rel="noopener">这篇文章</a>的分析。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">reverse</span><span class="params">(<span class="keyword">int</span> i)</span> </span>&#123;</span><br><span class="line">    i = (i &amp; <span class="number">0x55555555</span>) &lt;&lt; <span class="number">1</span> | (i &gt;&gt;&gt; <span class="number">1</span>) &amp; <span class="number">0x55555555</span>;</span><br><span class="line">    i = (i &amp; <span class="number">0x33333333</span>) &lt;&lt; <span class="number">2</span> | (i &gt;&gt;&gt; <span class="number">2</span>) &amp; <span class="number">0x33333333</span>;</span><br><span class="line">    i = (i &amp; <span class="number">0x0f0f0f0f</span>) &lt;&lt; <span class="number">4</span> | (i &gt;&gt;&gt; <span class="number">4</span>) &amp; <span class="number">0x0f0f0f0f</span>;</span><br><span class="line">    i = (i &lt;&lt; <span class="number">24</span>) | ((i &amp; <span class="number">0xff00</span>) &lt;&lt; <span class="number">8</span>) |</span><br><span class="line">        ((i &gt;&gt;&gt; <span class="number">8</span>) &amp; <span class="number">0xff00</span>) | (i &gt;&gt;&gt; <span class="number">24</span>);</span><br><span class="line">    <span class="keyword">return</span> i;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h1 id="5-二分搜索">5、二分搜索</h1>
<h2 id="二分搜索模板">二分搜索模板</h2>
<p>给定一个<strong>有序数组</strong>和目标值，找到第一次/最后一次/任何一次出现的索引，如果没有出现返回 -1。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">binarySearch</span><span class="params">(<span class="keyword">int</span>[] nums, <span class="keyword">int</span> target)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> mid, left = <span class="number">0</span>, right = nums.length - <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">while</span> (left &lt;= right) &#123;</span><br><span class="line">        mid = left + (right - left) / <span class="number">2</span>;</span><br><span class="line">        <span class="keyword">if</span> (target == nums[mid]) &#123;</span><br><span class="line">            <span class="keyword">return</span> mid;</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (target &lt; nums[mid]) &#123;</span><br><span class="line">            right = mid - <span class="number">1</span>;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            left = mid + <span class="number">1</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> -<span class="number">1</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><code>mid = left + (right-left)/2</code>  可以防止 <code>left+right</code> 溢出（超出整数范围）。</p>
<h2 id="704-二分查找">704. 二分查找</h2>
<p><a href="https://leetcode-cn.com/problems/binary-search/" target="_blank" rel="noopener">二分查找</a></p>
<blockquote>
<p>给定一个 n 个元素有序的（升序）整型数组 nums 和一个目标值 target  ，写一个函数搜索 nums 中的 target，如果目标值存在返回下标，否则返回 -1。</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">search</span><span class="params">(<span class="keyword">int</span>[] nums, <span class="keyword">int</span> target)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> mid, left = <span class="number">0</span>, right = nums.length - <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">while</span> (left &lt;= right) &#123;</span><br><span class="line">            mid = left + (right - left) / <span class="number">2</span>;</span><br><span class="line">            <span class="keyword">if</span> (target == nums[mid]) &#123;</span><br><span class="line">                <span class="keyword">return</span> mid;</span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (target &lt; nums[mid]) &#123;</span><br><span class="line">                right = mid - <span class="number">1</span>;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                left = mid + <span class="number">1</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> -<span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="35-搜索插入位置">35. 搜索插入位置</h2>
<p><a href="https://leetcode-cn.com/problems/search-insert-position/" target="_blank" rel="noopener">搜索插入位置</a></p>
<blockquote>
<p>给定一个排序数组和一个目标值，在数组中找到目标值，并返回其索引。如果目标值不存在于数组中，返回它将会被按顺序插入的位置。</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">searchInsert</span><span class="params">(<span class="keyword">int</span>[] nums, <span class="keyword">int</span> target)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> mid, left = <span class="number">0</span>, right = nums.length - <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">while</span> (left &lt;= right) &#123;</span><br><span class="line">            mid = left + (right - left) / <span class="number">2</span>;</span><br><span class="line">            <span class="keyword">if</span> (target == nums[mid]) &#123;</span><br><span class="line">                <span class="keyword">return</span> mid;</span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (target &lt; nums[mid]) &#123;</span><br><span class="line">                right = mid - <span class="number">1</span>;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                left = mid + <span class="number">1</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> left;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="74-搜索二维矩阵">74. 搜索二维矩阵</h2>
<p><a href="https://leetcode-cn.com/problems/search-a-2d-matrix/" target="_blank" rel="noopener">搜索二维矩阵</a></p>
<blockquote>
<p>编写一个高效的算法来判断 m x n 矩阵中，是否存在一个目标值。该矩阵具有如下特性：</p>
<p>每行中的整数从左到右按升序排列。<br>
每行的第一个整数大于前一行的最后一个整数。</p>
</blockquote>
<p>把 $m * n$ 的二维矩阵看作是一个长度为 $m * n$ 的数组，数组中的第 <code>mid</code> 个元素在二维矩阵中的位置是：</p>
<ul>
<li>行：<code>row = mid / n</code></li>
<li>列：<code>col = mid % n</code></li>
</ul>
<p>于是该问题就转换为了经典的二分搜索问题。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">searchMatrix</span><span class="params">(<span class="keyword">int</span>[][] matrix, <span class="keyword">int</span> target)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (matrix.length == <span class="number">0</span> || matrix[<span class="number">0</span>].length == <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">int</span> m = matrix.length, n = matrix[<span class="number">0</span>].length;</span><br><span class="line">        <span class="keyword">int</span> mid, left = <span class="number">0</span>, right = m * n - <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">while</span> (left &lt;= right) &#123;</span><br><span class="line">            mid = left + (right - left) / <span class="number">2</span>;</span><br><span class="line">            <span class="keyword">int</span> row = mid / n;</span><br><span class="line">            <span class="keyword">int</span> col = mid % n;</span><br><span class="line">            <span class="keyword">if</span> (target == matrix[row][col]) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (target &lt; matrix[row][col]) &#123;</span><br><span class="line">                right = mid - <span class="number">1</span>;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                left = mid + <span class="number">1</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="278-第一个错误的版本">278. 第一个错误的版本</h2>
<p><a href="https://leetcode-cn.com/problems/first-bad-version/" target="_blank" rel="noopener">第一个错误的版本</a></p>
<p>二分查找，如果 <code>isBadVersion(mid)</code> 返回 <code>false</code>，那么搜索空间确定为 [mid + 1, right]，如果 <code>isBadVersion(mid)</code> 返回 <code>true</code> 那么搜索空间确定为 [left, mid - 1]。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Solution</span> <span class="keyword">extends</span> <span class="title">VersionControl</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">firstBadVersion</span><span class="params">(<span class="keyword">int</span> n)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> mid, left = <span class="number">1</span>, right = n;</span><br><span class="line">        <span class="keyword">while</span> (left &lt;= right) &#123;</span><br><span class="line">            mid = left + (right - left) / <span class="number">2</span>;</span><br><span class="line">            <span class="keyword">if</span> (isBadVersion(mid)) &#123;</span><br><span class="line">                right = mid - <span class="number">1</span>;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                left = mid + <span class="number">1</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> left;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>另一个模板</strong></p>
<p><code>isBadVersion(mid)</code> 返回 <code>false</code>，因此我们知道 mid 左侧（包括自身）的所有版本都是正确的。所以我们令 <code>left = mid +1</code>，把下一次的搜索空间变为 [mid + 1, right]。</p>
<p><code>isBadVersion(mid)</code> 返回 <code>true</code>，因此我们知道 mid 右侧（不包括自身）的所有版本都不可能是第一个错误的版本。所以我们令 <code>right = mid</code>，把下一次的搜索空间变为 [left, mid]。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">firstBadVersion</span><span class="params">(<span class="keyword">int</span> n)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> left = <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">int</span> right = n;</span><br><span class="line">    <span class="keyword">while</span> (left &lt; right) &#123;</span><br><span class="line">        <span class="keyword">int</span> mid = left + (right - left) / <span class="number">2</span>;</span><br><span class="line">        <span class="keyword">if</span> (isBadVersion(mid)) &#123;</span><br><span class="line">            right = mid;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            left = mid + <span class="number">1</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> left;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="153-寻找旋转排序数组中的最小值">153. 寻找旋转排序数组中的最小值</h2>
<p><a href="https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array/" target="_blank" rel="noopener">寻找旋转排序数组中的最小值</a></p>
<blockquote>
<p>假设按照升序排序的数组在预先未知的某个点上进行了旋转。例如，数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] 。</p>
<p>请找出其中最小的元素。</p>
</blockquote>
<p>充分利用升序排序的特点。</p>
<p>需要注意的是为什么比较 <code>mid</code> 与 <code>right</code> 而不比较 <code>mid</code> 与 <code>left</code>？</p>
<p>因为这是旋转前<strong>升序</strong>排列的数，左边小，右边大。我们要找的是<strong>最小值</strong>，肯定是<strong>偏向左</strong>找，目标值右边的情况会比较简单，容易区分，所以比较 <code>mid</code> 与 <code>right</code> 而不比较 <code>mid</code> 与 <code>left</code>。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">findMin</span><span class="params">(<span class="keyword">int</span>[] nums)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> left = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">int</span> right = nums.length - <span class="number">1</span>;                <span class="comment">/* 左闭右闭区间，如果用右开区间则不方便判断右值 */</span> </span><br><span class="line">        <span class="keyword">while</span> (left &lt; right) &#123;                      <span class="comment">/* 循环不变式，如果left == right，则循环结束 */</span></span><br><span class="line">            <span class="keyword">int</span> mid = left + (right - left) / <span class="number">2</span>;    <span class="comment">/* 地板除，mid更靠近left */</span></span><br><span class="line">            <span class="keyword">if</span> (nums[mid] &gt; nums[right]) &#123;          <span class="comment">/* 中值 &gt; 右值，最小值在右半边，收缩左边界 */</span> </span><br><span class="line">                left = mid + <span class="number">1</span>;                     <span class="comment">/* 因为中值 &gt; 右值，中值肯定不是最小值，左边界可以跨过mid */</span> </span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (nums[mid] &lt; nums[right]) &#123;   <span class="comment">/* 明确中值 &lt; 右值，最小值在左半边，收缩右边界 */</span> </span><br><span class="line">                right = mid;                        <span class="comment">/* 因为中值 &lt; 右值，中值也可能是最小值，右边界只能取到mid处 */</span> </span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> nums[left];    <span class="comment">/* 循环结束，left == right，最小值输出nums[left]或nums[right]均可 */</span>     </span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
<h2 id="154-寻找旋转排序数组中的最小值-ii">154. 寻找旋转排序数组中的最小值 II</h2>
<p><a href="https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array-ii/" target="_blank" rel="noopener">寻找旋转排序数组中的最小值 II</a></p>
<blockquote>
<p>假设按照升序排序的数组在预先未知的某个点上进行了旋转。</p>
<p>( 例如，数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。</p>
<p>请找出其中最小的元素。</p>
<p>注意数组中可能存在重复的元素。</p>
</blockquote>
<p>二分法，不断缩小搜索空间。</p>
<blockquote>
<p>需要注意的是为什么比较 <code>mid</code> 与 <code>right</code> 而不比较 <code>mid</code> 与 <code>left</code>？</p>
<p>因为这是旋转前<strong>升序</strong>排列的数，左边小，右边大。我们要找的是<strong>最小值</strong>，肯定是<strong>偏向左</strong>找，目标值右边的情况会比较简单，容易区分，所以比较 <code>mid</code> 与 <code>right</code> 而不比较 <code>mid</code> 与 <code>left</code>。</p>
</blockquote>
<p>且因为有可能重复，所以重复的情况采用 <code>right--</code>，因为是升序的， <code>right &gt; left</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">findMin</span><span class="params">(<span class="keyword">int</span>[] nums)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> mid = <span class="number">0</span>, left = <span class="number">0</span>, right = nums.length - <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">while</span> (left &lt; right) &#123;</span><br><span class="line">            mid = left + (right - left) / <span class="number">2</span>;</span><br><span class="line">            <span class="keyword">if</span> (nums[mid] &gt; nums[right]) &#123;</span><br><span class="line">                left = mid + <span class="number">1</span>;</span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (nums[mid] &lt; nums[right]) &#123;</span><br><span class="line">                right = mid;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                right--;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> nums[left];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="33-搜索旋转排序数组">33. 搜索旋转排序数组</h2>
<p><a href="https://leetcode-cn.com/problems/search-in-rotated-sorted-array/" target="_blank" rel="noopener">搜索旋转排序数组</a></p>
<blockquote>
<p>升序排列的整数数组 nums 在预先未知的某个点上进行了旋转（例如， [0,1,2,4,5,6,7] 经旋转后可能变为 [4,5,6,7,0,1,2] ）。</p>
<p>请你在数组中搜索 target ，如果数组中存在这个目标值，则返回它的索引，否则返回 -1 。</p>
</blockquote>
<p><strong>最先想到的</strong> 和 153 题类似，于是套用相似思想，进行模拟。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">search</span><span class="params">(<span class="keyword">int</span>[] nums, <span class="keyword">int</span> target)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> mid, left = <span class="number">0</span>, right = nums.length - <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">while</span> (left &lt;= right) &#123;</span><br><span class="line">            mid = left + (right - left) / <span class="number">2</span>;</span><br><span class="line">            <span class="keyword">if</span> (target == nums[mid]) &#123;</span><br><span class="line">                <span class="keyword">return</span> mid;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (target == nums[left]) &#123;</span><br><span class="line">                <span class="keyword">return</span> left;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (target == nums[right]) &#123;</span><br><span class="line">                <span class="keyword">return</span> right;</span><br><span class="line">            &#125;            </span><br><span class="line">            <span class="keyword">if</span> (nums[left] &lt; nums[mid]) &#123;</span><br><span class="line">                <span class="comment">// [left, mid] 升序，[mid + 1, right] 存在最小值             </span></span><br><span class="line">                <span class="keyword">if</span> (target &lt; nums[mid]) &#123;</span><br><span class="line">                    <span class="comment">// target 可能存在于 mid 的左右两边</span></span><br><span class="line">                    <span class="keyword">if</span> (target &gt; nums[left]) &#123;</span><br><span class="line">                        <span class="comment">// target 在 [left + 1, mid - 1]</span></span><br><span class="line">                        left++;</span><br><span class="line">                        right = mid - <span class="number">1</span>;</span><br><span class="line">                    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (target &lt; nums[left])&#123;</span><br><span class="line">                        <span class="comment">// target 在 [mid + 1, right]</span></span><br><span class="line">                        left = mid + <span class="number">1</span>;</span><br><span class="line">                    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                        <span class="comment">// target == nums[left]</span></span><br><span class="line">                        <span class="keyword">return</span> left;</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    <span class="comment">// target &gt; nums[mid]</span></span><br><span class="line">                    <span class="comment">// target 可能存在于 [mid + 1, right]</span></span><br><span class="line">                    left = mid + <span class="number">1</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                <span class="comment">// nums[left] &gt;= nums[mid]</span></span><br><span class="line">                <span class="comment">// [mid, right] 升序，[left, mid] 存在最小值</span></span><br><span class="line">                <span class="keyword">if</span> (target &lt; nums[mid]) &#123;</span><br><span class="line">                    <span class="comment">// target 可能在[left, mid - 1]</span></span><br><span class="line">                    right = mid - <span class="number">1</span>;</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    <span class="comment">// target &gt; nums[mid]</span></span><br><span class="line">                    <span class="comment">// target 在 mid 左右都可能</span></span><br><span class="line">                    <span class="keyword">if</span> (target &gt; nums[left]) &#123;</span><br><span class="line">                        <span class="comment">// target 在 [left + 1, mid - 1]</span></span><br><span class="line">                        left++;</span><br><span class="line">                        right = mid - <span class="number">1</span>;</span><br><span class="line">                    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (target &lt; nums[left]) &#123;</span><br><span class="line">                        <span class="comment">// target 在 [mid + 1, right]</span></span><br><span class="line">                        left = mid + <span class="number">1</span>;</span><br><span class="line">                    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                        <span class="comment">// target == nums[left]</span></span><br><span class="line">                        <span class="keyword">return</span> left;</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> -<span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>简洁版本</strong> 先确定 mid 和左段、右端的关系，接下来再判断 target 在 mid 的左边还是右边。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">search</span><span class="params">(<span class="keyword">int</span>[] nums, <span class="keyword">int</span> target)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> mid, left = <span class="number">0</span>, right = nums.length - <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">while</span> (left &lt;= right) &#123;</span><br><span class="line">            mid = left + (right - left) / <span class="number">2</span>;</span><br><span class="line">            <span class="keyword">if</span> (target == nums[mid]) &#123;</span><br><span class="line">                <span class="keyword">return</span> mid;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (target == nums[left]) &#123;</span><br><span class="line">                <span class="keyword">return</span> left;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (target == nums[right]) &#123;</span><br><span class="line">                <span class="keyword">return</span> right;</span><br><span class="line">            &#125;            </span><br><span class="line">            <span class="keyword">if</span> (nums[left] &lt; nums[mid]) &#123;</span><br><span class="line">                <span class="comment">// [left, mid] 升序，[mid + 1, right] 存在最小值</span></span><br><span class="line">                <span class="keyword">if</span> (target &gt; nums[left] &amp;&amp; target &lt; nums[mid]) &#123;</span><br><span class="line">                    <span class="comment">// 说明 target 在 [left + 1， mid - 1]</span></span><br><span class="line">                    right = mid - <span class="number">1</span>;</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    <span class="comment">// target &gt; nums[left] &amp;&amp; target &gt; nums[mid] ==&gt; target 在 [mid + 1, right]</span></span><br><span class="line">                    <span class="comment">// target &lt; nums[left] &amp;&amp; target &lt; nums[mid] ==&gt; target 在 [mid + 1, right]</span></span><br><span class="line">                    <span class="comment">// target &lt; nums[left] &amp;&amp; target &gt; nums[mid] ==&gt; target 在 [mid + 1, right]</span></span><br><span class="line">                    left = mid + <span class="number">1</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                <span class="comment">// nums[left] &gt; nums[mid]</span></span><br><span class="line">                <span class="comment">// [mid, right] 升序，</span></span><br><span class="line">                <span class="keyword">if</span> (target &lt; nums[right] &amp;&amp; target &gt; nums[mid]) &#123;</span><br><span class="line">                    <span class="comment">// 说明 target 在 [mid + 1, right - 1]</span></span><br><span class="line">                    left = mid + <span class="number">1</span>;</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    <span class="comment">// target &lt; nums[right] &amp;&amp; target &lt; nums[mid] ==&gt; target 在 [left, mid - 1]</span></span><br><span class="line">                    <span class="comment">// target &gt; nums[right] &amp;&amp; target &lt; nums[mid] ==&gt; target 在 [left, mid - 1]</span></span><br><span class="line">                    <span class="comment">// target &gt; nums[right] &amp;&amp; target &gt; nums[mid] ==&gt; target 在 [left, mid - 1]</span></span><br><span class="line">                    right = mid - <span class="number">1</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> -<span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="81-搜索旋转排序数组-ii">81. 搜索旋转排序数组 II</h2>
<p><a href="https://leetcode-cn.com/problems/search-in-rotated-sorted-array-ii/" target="_blank" rel="noopener">搜索旋转排序数组 II</a></p>
<blockquote>
<p>假设按照升序排序的数组在预先未知的某个点上进行了旋转。</p>
<p>( 例如，数组 [0,0,1,2,2,5,6] 可能变为 [2,5,6,0,0,1,2] )。</p>
<p>编写一个函数来判断给定的目标值是否存在于数组中。若存在返回 true，否则返回 false。</p>
</blockquote>
<p><strong>思路</strong></p>
<ul>
<li>
<p>第一类</p>
<p><code>10111</code> 和 <code>11101</code> 这种。此种情况下 <code>nums[left] == nums[right]</code>，分不清到底前面有序还是后面有序，此时 <code>left++</code> 进行处理。相当于去掉了一个重复的干扰项。</p>
</li>
<li>
<p>第二类</p>
<p><code>2345671</code> 这种，也就是 <code>num[left] &lt; nums[right]</code>，即 <code>2 &lt; 5</code>，这种情况下前半部分有序。因此如果 <code>nums[left] &lt; target &lt; nums[mid]</code>，则在前半部分找，否则去后半部分找。</p>
</li>
<li>
<p>第三类</p>
<p><code>6712345</code> 这种，也就是 <code>nums[left] &gt; nums[mid]</code>，即 <code>6 &gt; 2</code>，这种情况下，后半部分有序。因此如果 <code>nums[mid] &lt; target &lt; nums[right]</code>，则在后半部分找，否则去前半部分找。</p>
</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">search</span><span class="params">(<span class="keyword">int</span>[] nums, <span class="keyword">int</span> target)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> mid, left = <span class="number">0</span>, right = nums.length - <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">while</span> (left &lt;= right) &#123;</span><br><span class="line">            mid = left + (right - left) / <span class="number">2</span>;</span><br><span class="line">            <span class="keyword">if</span> (target == nums[mid]) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (target == nums[left]) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (target == nums[right]) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> (nums[mid] &lt; nums[left]) &#123;</span><br><span class="line">                <span class="comment">// [mid, right] 升序</span></span><br><span class="line">                <span class="keyword">if</span> (target &gt; nums[mid] &amp;&amp; target &lt; nums[right]) &#123;</span><br><span class="line">                    <span class="comment">// target 在 [mid + 1, right]</span></span><br><span class="line">                    left = mid + <span class="number">1</span>;</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    <span class="comment">// target &gt; nums[mid] &amp;&amp; target &gt; nums[right] ==&gt; target 在 [left, mid - 1]</span></span><br><span class="line">                    <span class="comment">// target &lt; nums[mid] ==&gt; target 在 [left, mid - 1]</span></span><br><span class="line">                    right = mid - <span class="number">1</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (nums[mid] &gt; nums[left]) &#123;</span><br><span class="line">                <span class="comment">// [left, mid] 升序</span></span><br><span class="line">                <span class="keyword">if</span> (target &lt; nums[mid] &amp;&amp; target &gt; nums[left]) &#123;</span><br><span class="line">                    <span class="comment">// target 在 [left, mid - 1]</span></span><br><span class="line">                    right = mid - <span class="number">1</span>;</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    <span class="comment">// target &lt; nums[mid] &amp;&amp; target &lt; nums[left] ==&gt; target 在 [mid + 1, right]</span></span><br><span class="line">                    <span class="comment">// target &gt; nums[mid] ==&gt; target 在 [mid + 1, right]</span></span><br><span class="line">                    left = mid + <span class="number">1</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                <span class="comment">// left == mid，left 可以排除</span></span><br><span class="line">                left++;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h1 id="6-排序算法">6、排序算法</h1>
<p><a href="https://www.cnblogs.com/onepixel/p/7674659.html" target="_blank" rel="noopener">十大经典排序算法</a></p>
<h2 id="归并排序">归并排序</h2>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">mergeSort</span><span class="params">(<span class="keyword">int</span>[] array, <span class="keyword">int</span> start, <span class="keyword">int</span> end)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (start &gt;= end) &#123;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span> mid = start + (end - start) / <span class="number">2</span>;</span><br><span class="line">    mergeSort(array, start, mid);</span><br><span class="line">    mergeSort(array, mid + <span class="number">1</span>, end);</span><br><span class="line">    merge(array, start, end, mid);</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">merge</span><span class="params">(<span class="keyword">int</span>[] array, <span class="keyword">int</span> start, <span class="keyword">int</span> end, <span class="keyword">int</span> mid)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span>[] temp = <span class="keyword">new</span> <span class="keyword">int</span>[end - start + <span class="number">1</span>];</span><br><span class="line">    <span class="keyword">int</span> p1 = start;</span><br><span class="line">    <span class="keyword">int</span> p2 = mid + <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">int</span> k = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">while</span> (p1 &lt;= mid &amp;&amp; p2 &lt;= end) &#123;</span><br><span class="line">        <span class="keyword">if</span> (array[p1] &lt; array[p2]) &#123;</span><br><span class="line">            temp[k++] = array[p1++];</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            temp[k++] = array[p2++];</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">while</span> (p1 &lt;= mid) &#123;</span><br><span class="line">        temp[k++] = array[p1++];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">while</span> (p2 &lt;= end) &#123;</span><br><span class="line">        temp[k++] = array[p2++];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">int</span> i = start; i &lt;= end; i++) &#123;</span><br><span class="line">        array[i] = temp[i - start];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="堆排序">堆排序</h2>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.Arrays;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span>[] array = &#123;<span class="number">7</span>, <span class="number">6</span>, <span class="number">5</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">2</span>, <span class="number">1</span>&#125;;</span><br><span class="line">        heapSort(array);</span><br><span class="line">        System.out.println(Arrays.toString(array));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">heapSort</span><span class="params">(<span class="keyword">int</span>[] array)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 1.构建大根堆</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = array.length / <span class="number">2</span> - <span class="number">1</span>; i &gt;= <span class="number">0</span>; i--) &#123;</span><br><span class="line">            <span class="comment">// 从第一个非叶子结点开始，从下至上，从右至左调整结构</span></span><br><span class="line">            adjustHeap(array, i, array.length);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 2.调整堆结构+交换堆顶元素与堆尾元素</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = array.length - <span class="number">1</span>; i &gt;= <span class="number">0</span>; i--) &#123;</span><br><span class="line">            <span class="comment">// 交换堆顶元素和堆尾元素</span></span><br><span class="line">            swap(array, <span class="number">0</span>, i);</span><br><span class="line">            <span class="comment">// 重新对堆进行调整</span></span><br><span class="line">            adjustHeap(array, <span class="number">0</span>, i);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 调整大顶堆，仅仅在已经创建好的基础上，对第i个元素进行调整</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> array</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> i</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> length</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">adjustHeap</span><span class="params">(<span class="keyword">int</span>[] array, <span class="keyword">int</span> i, <span class="keyword">int</span> length)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 1.取出当前元素</span></span><br><span class="line">        <span class="keyword">int</span> temp = array[i];</span><br><span class="line">        <span class="comment">// 2.从第i个节点的左子节点开始，即第2*i+1处开始</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> k = <span class="number">2</span> * i + <span class="number">1</span>; k &lt; length; k = <span class="number">2</span> * k + <span class="number">1</span>) &#123;</span><br><span class="line">            <span class="comment">// 如果右子节点大于左子节点，k指向右子节点</span></span><br><span class="line">            <span class="keyword">if</span> (k + <span class="number">1</span> &lt; length &amp;&amp; array[k] &lt; array[k + <span class="number">1</span>]) &#123;</span><br><span class="line">                k++;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">// 如果子节点的值大于父节点，将子节点的值赋给父节点</span></span><br><span class="line">            <span class="keyword">if</span> (array[k] &gt; temp) &#123;</span><br><span class="line">                array[i] = array[k];</span><br><span class="line">                i = k;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 将temp放置到最终的位置</span></span><br><span class="line">        array[i] = temp;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">swap</span><span class="params">(<span class="keyword">int</span>[] array, <span class="keyword">int</span> i, <span class="keyword">int</span> j)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> temp = array[i];</span><br><span class="line">        array[i] = array[j];</span><br><span class="line">        array[j] = temp;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h1 id="7-动态规划">7、动态规划</h1>
<h2 id="下面是矩阵dp"><strong>下面是矩阵dp</strong></h2>
<h2 id="120-三角形最小路径和">120. 三角形最小路径和</h2>
<p><a href="https://leetcode-cn.com/problems/triangle/" target="_blank" rel="noopener">三角形最小路径和</a></p>
<blockquote>
<p>给定一个三角形，找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。</p>
<p>相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 + 1 的两个结点。</p>
</blockquote>
<p><strong>自底向上</strong>   自底向上的优势是①可以规避边界问题，②出口 dp[0] 就是最终答案。</p>
<p>假设<code>dp[i][j]</code> 表示第 i 层第 j 个元素开始向下的最小路径和，那么有</p>
<p><code>dp[i][j] = min(dp[i+1][j], dp[i+1][j+1]) + triangle[i][j]​</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">minimumTotal</span><span class="params">(List&lt;List&lt;Integer&gt;&gt; triangle)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> n = triangle.size();</span><br><span class="line">        <span class="keyword">int</span>[][] dp = <span class="keyword">new</span> <span class="keyword">int</span>[n + <span class="number">1</span>][n + <span class="number">1</span>];</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = n - <span class="number">1</span>; i &gt;= <span class="number">0</span>; i--) &#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">0</span>; j &lt;= i; j++) &#123;</span><br><span class="line">                dp[i][j] = Math.min(dp[i + <span class="number">1</span>][j], dp[i + <span class="number">1</span>][j + <span class="number">1</span>]) + triangle.get(i).get(j);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> dp[<span class="number">0</span>][<span class="number">0</span>];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>空间优化复杂度O(N)</strong></p>
<p>在实际地推中，计算 <code>dp[i][j]</code> 只用到了 <code>dp[i+1][j]</code> 和 <code>dp[i+1][j+1]</code>，因此 dp 数组不需要定义成 N 行，只需要定义一行就够了。</p>
<p>在计算最底层 <code>[4,1,8,3]</code> 的时候，计算结果是</p>
<p><img src="https://pic.tyzhang.top/images/2020/12/26/image.png" alt="image.png"></p>
<p>然后在计算上一层 <code>[6,5,7]</code> 的时候，当计算到 <code>6</code> 时我们只需要用到 <code>dp[0]</code> 和 <code>dp[1]</code>，然后将计算出来的结果更新到 <code>dp[0]</code>；</p>
<p><img src="https://pic.tyzhang.top/images/2020/12/26/image45505e2ffbc71442.png" alt="image45505e2ffbc71442.png"></p>
<p>计算 <code>5</code> 的时候，需要用到 <code>dp[1]</code> 和 <code>dp[2]</code>，然后将计算出来的结果更新到 <code>dp[1]</code>。</p>
<p>可见，我们将空间优化到一维数组是完全可行的，每一行计算的时候更新一次 dp 数组。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">minimumTotal</span><span class="params">(List&lt;List&lt;Integer&gt;&gt; triangle)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> n = triangle.size();</span><br><span class="line">        <span class="keyword">int</span>[] dp = <span class="keyword">new</span> <span class="keyword">int</span>[n + <span class="number">1</span>];</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = n - <span class="number">1</span>; i &gt;= <span class="number">0</span>; i--) &#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">0</span>; j &lt;= i; j++) &#123;</span><br><span class="line">                dp[j] = Math.min(dp[j], dp[j + <span class="number">1</span>]) + triangle.get(i).get(j); </span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> dp[<span class="number">0</span>];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="64-最小路径和">64. 最小路径和</h2>
<p><a href="https://leetcode-cn.com/problems/minimum-path-sum/" target="_blank" rel="noopener">最小路径和</a></p>
<blockquote>
<p>给定一个包含非负整数的 <code>*m* x *n*</code> 网格 <code>grid</code> ，请找出一条从左上角到右下角的路径，使得路径上的数字总和为最小。</p>
<p>**说明：**每次只能向下或者向右移动一步。</p>
</blockquote>
<p>在左边和上边添 0</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">0 0 0 0 </span><br><span class="line">0 1 3 1 </span><br><span class="line">0 1 5 1 </span><br><span class="line">0 4 2 1</span><br></pre></td></tr></table></figure>
<p>方便 dp 数组初始化。</p>
<p>代码：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">minPathSum</span><span class="params">(<span class="keyword">int</span>[][] grid)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> n = grid.length, m = grid[<span class="number">0</span>].length;</span><br><span class="line">        <span class="keyword">int</span>[][] dp = <span class="keyword">new</span> <span class="keyword">int</span>[n + <span class="number">1</span>][m + <span class="number">1</span>];</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> row = <span class="number">1</span>; row &lt;= n; row++) &#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> col = <span class="number">1</span>; col &lt;= m; col++) &#123;</span><br><span class="line">                <span class="keyword">if</span> (row == <span class="number">1</span>) &#123;</span><br><span class="line">                    <span class="comment">// 第一行只能是往右走得到的最小路径和</span></span><br><span class="line">                    dp[row][col] = dp[row][col - <span class="number">1</span>] + grid[row - <span class="number">1</span>][col - <span class="number">1</span>];</span><br><span class="line">                &#125; <span class="keyword">else</span> <span class="keyword">if</span> (col == <span class="number">1</span>) &#123;</span><br><span class="line">                    <span class="comment">// 第一列只能是往下走得到的最小路径和</span></span><br><span class="line">                    dp[row][col] = dp[row - <span class="number">1</span>][col] + grid[row - <span class="number">1</span>][col - <span class="number">1</span>];</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    dp[row][col] = Math.min(dp[row - <span class="number">1</span>][col], dp[row][col - <span class="number">1</span>]) + grid[row - <span class="number">1</span>][col - <span class="number">1</span>];</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> dp[n][m];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="62-不同路径">62. 不同路径</h2>
<p><a href="https://leetcode-cn.com/problems/unique-paths/" target="_blank" rel="noopener">不同路径</a></p>
<blockquote>
<p>一个机器人位于一个 m x n 网格的左上角 （起始点在下图中标记为 “Start” ）。</p>
<p>机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角（在下图中标记为 “Finish” ）。</p>
<p>问总共有多少条不同的路径？</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">uniquePaths</span><span class="params">(<span class="keyword">int</span> m, <span class="keyword">int</span> n)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span>[][] dp = <span class="keyword">new</span> <span class="keyword">int</span>[m][n];</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 第一行都只能从左边过来，所以只有一条路</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; n; i++) &#123;</span><br><span class="line">            dp[<span class="number">0</span>][i] = <span class="number">1</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 第一列都只能从上边过来，所以只有一条路</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; m; i++) &#123;</span><br><span class="line">            dp[i][<span class="number">0</span>] = <span class="number">1</span>;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// dp[row][col] 可以来自它的左边或者是上边，所以它的路径等于左边的路径与上边的路径之和</span></span><br><span class="line">        <span class="comment">// dp[row][col] = dp[row - 1][col] + dp[row][col - 1]</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> row = <span class="number">1</span>; row &lt; m; row++) &#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> col = <span class="number">1</span>; col &lt; n; col++) &#123;</span><br><span class="line">                dp[row][col] = dp[row - <span class="number">1</span>][col] + dp[row][col - <span class="number">1</span>];</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> dp[m - <span class="number">1</span>][n -<span class="number">1</span>];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="63-不同路径-ii滚动数组优化空间复杂度">63. 不同路径 II【滚动数组优化空间复杂度】</h2>
<p><a href="https://leetcode-cn.com/problems/unique-paths-ii/" target="_blank" rel="noopener">不同路径 II</a></p>
<blockquote>
<p>一个机器人位于一个 m x n 网格的左上角 （起始点在下图中标记为“Start” ）。</p>
<p>机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角（在下图中标记为“Finish”）。</p>
<p>现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径？</p>
</blockquote>
<p>二维数组动态规划</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">uniquePathsWithObstacles</span><span class="params">(<span class="keyword">int</span>[][] obstacleGrid)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (obstacleGrid[<span class="number">0</span>][<span class="number">0</span>] == <span class="number">1</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">int</span> m = obstacleGrid.length, n = obstacleGrid[<span class="number">0</span>].length;</span><br><span class="line">        <span class="keyword">int</span>[][] dp = <span class="keyword">new</span> <span class="keyword">int</span>[m][n];</span><br><span class="line">        dp[<span class="number">0</span>][<span class="number">0</span>] = <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 第一行的格子，只能来自左边</span></span><br><span class="line">        <span class="comment">// 如果当前格子有障碍物，那么它将没办法到达</span></span><br><span class="line">        <span class="comment">// 如果当前格子没有障碍物，那么它只能从左边到达（此时依赖左边的所有格子之中有没有障碍物），所以路径数等于它左边的格子</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt; n; i++) &#123;</span><br><span class="line">            <span class="keyword">if</span> (obstacleGrid[<span class="number">0</span>][i] == <span class="number">1</span>) &#123;</span><br><span class="line">                dp[<span class="number">0</span>][i] = <span class="number">0</span>;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                dp[<span class="number">0</span>][i] = dp[<span class="number">0</span>][i - <span class="number">1</span>];</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 第一列的格子，只能来自上边</span></span><br><span class="line">        <span class="comment">// 如果当前格子有障碍物，那么它将没办法到达</span></span><br><span class="line">        <span class="comment">// 如果当前格子没有障碍物，那么它只能从上边到达（此时依赖上边的所有格子之中有没有障碍物），所以路径数等于它上边的格子</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt; m; i++) &#123;</span><br><span class="line">            <span class="keyword">if</span> (obstacleGrid[i][<span class="number">0</span>] == <span class="number">1</span>) &#123;</span><br><span class="line">                dp[i][<span class="number">0</span>] = <span class="number">0</span>;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                dp[i][<span class="number">0</span>] = dp[i - <span class="number">1</span>][<span class="number">0</span>];</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 中间的格子则来自左边或上边</span></span><br><span class="line">        <span class="comment">// 如果有障碍物，那就没办法到达</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt; m; i++) &#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">1</span>; j &lt; n; j++) &#123;</span><br><span class="line">                <span class="keyword">if</span> (obstacleGrid[i][j] == <span class="number">1</span>) &#123;</span><br><span class="line">                    dp[i][j] = <span class="number">0</span>;</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    dp[i][j] = dp[i][j - <span class="number">1</span>] + dp[i - <span class="number">1</span>][j];</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> dp[m - <span class="number">1</span>][n - <span class="number">1</span>];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>利用滚动数组优化空间复杂度</strong></p>
<p>简单的理解就是让数组滚动起来，每次都使用固定的几个存储空间，来达到压缩，节省存储空间的作用。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">uniquePathsWithObstacles</span><span class="params">(<span class="keyword">int</span>[][] obstacleGrid)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> n = obstacleGrid.length, m = obstacleGrid[<span class="number">0</span>].length;</span><br><span class="line">        <span class="keyword">int</span>[] dp = <span class="keyword">new</span> <span class="keyword">int</span>[m];</span><br><span class="line">        dp[<span class="number">0</span>] = obstacleGrid[<span class="number">0</span>][<span class="number">0</span>] == <span class="number">0</span> ? <span class="number">1</span> : <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; n; i++) &#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">0</span>; j &lt; m; j++) &#123;</span><br><span class="line">                <span class="keyword">if</span> (obstacleGrid[i][j] == <span class="number">1</span>) &#123;</span><br><span class="line">                    dp[j] = <span class="number">0</span>;</span><br><span class="line">                    <span class="keyword">continue</span>;</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">if</span> (j - <span class="number">1</span> &gt;= <span class="number">0</span> &amp;&amp; obstacleGrid[i][j] == <span class="number">0</span>) &#123;</span><br><span class="line">                    dp[j] = dp[j] + dp[j - <span class="number">1</span>];</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> dp[m - <span class="number">1</span>];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="下面是序列dp">下面是序列dp</h2>
<h2 id="70-爬楼梯">70. 爬楼梯</h2>
<p><a href="https://leetcode-cn.com/problems/climbing-stairs/" target="_blank" rel="noopener">爬楼梯</a></p>
<blockquote>
<p>假设你正在爬楼梯。需要 <em>n</em> 阶你才能到达楼顶。</p>
<p>每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢？</p>
<p>**注意：**给定 <em>n</em> 是一个正整数。</p>
</blockquote>
<p>第 n 个台阶只能从第 n-1 或者 n-2 个上来。到第 n-1 个台阶的走法 + 第 n-2 个台阶的走法 = 到第 n 个台阶的走法，已经知道了第 1 个和第 2 个台阶的走法，一路加上去。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">climbStairs</span><span class="params">(<span class="keyword">int</span> n)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (n == <span class="number">1</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">if</span> (n == <span class="number">2</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="number">2</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">int</span> a = <span class="number">1</span>, b = <span class="number">2</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">3</span>; i &lt;= n; i++) &#123;</span><br><span class="line">            <span class="keyword">int</span> temp = b;</span><br><span class="line">            b = a + b;</span><br><span class="line">            a = temp;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> b;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="55-跳跃游戏">55. 跳跃游戏</h2>
<p><a href="https://leetcode-cn.com/problems/jump-game/" target="_blank" rel="noopener">跳跃游戏</a></p>
<blockquote>
<p>给定一个非负整数数组，你最初位于数组的第一个位置。</p>
<p>数组中的每个元素代表你在该位置可以跳跃的最大长度。</p>
<p>判断你是否能够到达最后一个位置。</p>
</blockquote>
<p><strong>动态规划</strong></p>
<p><code>dp[i]</code> 能否到达取决于 <code>dp[0] ~ dp[i - 1]</code> 之中有没有 <code>nums[j] + j ≥ i</code> 的。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">canJump</span><span class="params">(<span class="keyword">int</span>[] nums)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> n = nums.length;</span><br><span class="line">        <span class="keyword">boolean</span>[] dp = <span class="keyword">new</span> <span class="keyword">boolean</span>[n];</span><br><span class="line">        dp[<span class="number">0</span>] = <span class="keyword">true</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt; n; i++) &#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">0</span>; j &lt; i; j++) &#123;</span><br><span class="line">                <span class="keyword">if</span> (dp[j] == <span class="keyword">true</span> &amp;&amp; nums[j] + j &gt;= i) &#123;</span><br><span class="line">                    dp[i] = <span class="keyword">true</span>;</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> dp[n - <span class="number">1</span>];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>贪心</strong></p>
<p>对于每一个可以到达的位置 <code>x</code>，它使得 <code>x+1,x+2,⋯,x+nums[x]</code> 这些连续的位置都可以到达。</p>
<p>依次遍历数组中的每一个位置，维护最远可以到达的位置。对于当前遍历到的位置 <code>x</code>，如果它在最远可以到达的位置的范围内，那么我们就可以从起点通过若干次跳跃到达该位置，因此我们可以用 <code>x + nums[x]</code> 来更新最远可以到达的位置。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">canJump</span><span class="params">(<span class="keyword">int</span>[] nums)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> longestLocation = <span class="number">0</span>, n = nums.length;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; n; i++) &#123;</span><br><span class="line">            <span class="keyword">if</span> (i &lt;= longestLocation) &#123;</span><br><span class="line">                longestLocation = Math.max(longestLocation, i + nums[i]);</span><br><span class="line">                <span class="keyword">if</span> (longestLocation &gt;= n - <span class="number">1</span>) &#123;</span><br><span class="line">                    <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="45-跳跃游戏-ii">45. 跳跃游戏 II</h2>
<p><a href="https://leetcode-cn.com/problems/jump-game-ii/" target="_blank" rel="noopener">跳跃游戏 II</a></p>
<blockquote>
<p>给定一个非负整数数组，你最初位于数组的第一个位置。</p>
<p>数组中的每个元素代表你在该位置可以跳跃的最大长度。</p>
<p>你的目标是使用最少的跳跃次数到达数组的最后一个位置。</p>
</blockquote>
<p><strong>动态规划</strong></p>
<p>dp[i] 保存到达该位置 i 所需要的最少跳跃次数。初始 <code>dp[0] = 0</code>，其余位置为 <code>Integer.MAX_VALUE</code>。</p>
<p>假设当前遍历到第 i 个元素，那么第 i 个元素能够跳跃到达的位置为 <code>[i + 1, i + nums[i]]</code>，那么到达 <code>[i + 1, i + nums[i]]</code> 这些元素的跳跃次数为 <code>dp[j] = Math.min(dp[j], dp[i] + 1), j = [i + 1， i + nums[i]]</code>。即通过遍历每一个位置，来更新当前位置所能到达位置 j 处所需要的最少的跳跃次数。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">jump</span><span class="params">(<span class="keyword">int</span>[] nums)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> n = nums.length;</span><br><span class="line">        <span class="keyword">int</span>[] dp = <span class="keyword">new</span> <span class="keyword">int</span>[n];</span><br><span class="line"></span><br><span class="line">        dp[<span class="number">0</span>] = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt; n; i++) &#123;</span><br><span class="line">            dp[i] = Integer.MAX_VALUE;</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; n; i++) &#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> j = i; j &lt; n &amp;&amp; j &lt;= i + nums[i]; j++) &#123;</span><br><span class="line">                dp[j] = Math.min(dp[j], dp[i] + <span class="number">1</span>);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> dp[n - <span class="number">1</span>];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>贪心</strong></p>
<p>当前所在位置为 i，选择第i个元素能到达的位置 <code>[i + 1, i + nums[i]]</code> 中，再跳一次能到达的最远位置。即下一个跳跃落点的位置最好是它能跳的越远越好。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">jump</span><span class="params">(<span class="keyword">int</span>[] nums)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> n = nums.length;</span><br><span class="line">        <span class="keyword">int</span> step = <span class="number">0</span>, end = <span class="number">0</span>, maxPosition = <span class="number">0</span>;</span><br><span class="line">        <span class="comment">// 在边界正好为最后一个位置的情况下，就没有必要再跳了</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; n - <span class="number">1</span>; i++) &#123;</span><br><span class="line">            maxPosition = Math.max(maxPosition, i + nums[i]);</span><br><span class="line">            <span class="keyword">if</span> (i == end) &#123;</span><br><span class="line">                end = maxPosition;</span><br><span class="line">                step++;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> step;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="132-分割回文串-ii">132. 分割回文串 II</h2>
<p><a href="https://leetcode-cn.com/problems/palindrome-partitioning-ii/" target="_blank" rel="noopener">分割回文串 II</a></p>
<blockquote>
<p>给定一个字符串 <em>s</em>，将 <em>s</em> 分割成一些子串，使每个子串都是回文串。</p>
<p>返回符合要求的最少分割次数。</p>
</blockquote>
<p>1、首先进行预处理，标记 <code>preDp[i][j]</code> 表示字符串子序列 <code>[i, j]</code> 是否是回文串；</p>
<p>2、动态规划：</p>
<p><code>dp[i]</code> 表示 <code>[0, i]</code> 所需要的最少分割次数，假设 <code>[0, i]</code> 内某处 <code>j</code> 有 <code>[j, i]</code> 是回文串，那么可以理解为在 <code>j - 1</code> 和 <code>j</code> 处切一刀，将 <code>[0, i]</code> 分割为 <code>[0, j - 1]</code> 和 <code>[j, i]</code>，此时可以得出状态转移方程：</p>
<p><code>dp[i] = min(dp[i], dp[j - 1] + 1)</code>，其中 <code>dp[j - 1]</code> 表示 <code>[0, j - 1]</code> 所需要的最小分割次数， <code>+1</code> 表示加上切的 <code>j - 1</code> 和 <code>j</code> 处的这一刀，与 <code>dp[i]</code>  比较是因为这一轮会一直计算 <code>dp[i]</code> 的值，更新保留一个最小值即可。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">minCut</span><span class="params">(String s)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> n = s.length();</span><br><span class="line">        <span class="keyword">boolean</span>[][] preDp = <span class="keyword">new</span> <span class="keyword">boolean</span>[n][n];</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; s.length(); i++) &#123;</span><br><span class="line">            prePro(preDp, s, i, i);</span><br><span class="line">            prePro(preDp, s, i, i + <span class="number">1</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        <span class="comment">// dp[i] 表示 [0, i] 切割成符合要求的最少分割次数</span></span><br><span class="line">        <span class="comment">// 当 [j, i] 是回文子串时，从 j - 1 和 j 中间切一刀分为 [0, j - 1] 和 [j, i]</span></span><br><span class="line">        <span class="comment">// 那么 dp[i] = dp[j - 1] + 1, dp[j - 1] 表示 [0, j - 1] 切割成符合要求的最少分割次数，1 表示切 j - 1 和 j 中间的这一刀。</span></span><br><span class="line">        <span class="comment">// 同时 dp[i] 更新时也需要和 dp[i] 本身的值作比较，找到最少的切割次数</span></span><br><span class="line">        <span class="keyword">int</span>[] dp = <span class="keyword">new</span> <span class="keyword">int</span>[n];</span><br><span class="line">        Arrays.fill(dp, n);</span><br><span class="line">        dp[<span class="number">0</span>] = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt; n; i++) &#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">0</span>; j &lt;= i; j++) &#123;</span><br><span class="line">                <span class="keyword">if</span> (preDp[j][i] == <span class="keyword">true</span>) &#123;</span><br><span class="line">                    <span class="keyword">if</span> (j == <span class="number">0</span>) &#123;</span><br><span class="line">                        dp[i] = <span class="number">0</span>;</span><br><span class="line">                    &#125; <span class="keyword">else</span>&#123;</span><br><span class="line">                        dp[i] = Math.min(dp[i], dp[j - <span class="number">1</span>] + <span class="number">1</span>);</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;    </span><br><span class="line">        <span class="comment">// System.out.println(preDp[0][1] + " " + dp[1]);</span></span><br><span class="line">        <span class="keyword">return</span> dp[n - <span class="number">1</span>];</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">prePro</span><span class="params">(<span class="keyword">boolean</span>[][] preDp, String s, <span class="keyword">int</span> left, <span class="keyword">int</span> right)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">while</span> (left &gt;= <span class="number">0</span> &amp;&amp; right &lt; s.length() &amp;&amp; s.charAt(left) == s.charAt(right)) &#123;</span><br><span class="line">            preDp[left][right] = <span class="keyword">true</span>;</span><br><span class="line">            left--;</span><br><span class="line">            right++;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="300-最长递增子序列">300. 最长递增子序列</h2>
<p><a href="https://leetcode-cn.com/problems/longest-increasing-subsequence/" target="_blank" rel="noopener">最长递增子序列</a></p>
<blockquote>
<p>给你一个整数数组 nums ，找到其中最长严格递增子序列的长度。</p>
<p>子序列是由数组派生而来的序列，删除（或不删除）数组中的元素而不改变其余元素的顺序。例如，[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。</p>
</blockquote>
<p><strong>动态规划</strong></p>
<p><code>dp[i]</code> 表示以第 i 个元素结尾的子序列中，最长严格递增子序列的长度是 <code>dp[i]</code>。假设有 <code>nums[j] &lt; nums[i]</code> 且 <code>dp[j]</code> 是 <code>dp[0] ~ dp[i - 1]</code> 中最大的一个。于是有</p>
<p><code>dp[i] = max(dp[j]) + 1</code>，其中 <code>0 ≤ j &lt; i</code> 且 <code>nums[j] &lt; nums[i]</code>。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">lengthOfLIS</span><span class="params">(<span class="keyword">int</span>[] nums)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> n = nums.length, maxLength = <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">int</span>[] dp = <span class="keyword">new</span> <span class="keyword">int</span>[n];</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; n; i++) &#123;</span><br><span class="line">            dp[i] = <span class="number">1</span>;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">0</span>; j &lt; i; j++) &#123;</span><br><span class="line">                <span class="keyword">if</span> (nums[j] &lt; nums[i]) &#123;</span><br><span class="line">                    dp[i] = Math.max(dp[i], dp[j] + <span class="number">1</span>);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            maxLength = Math.max(maxLength, dp[i]);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> maxLength;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="139-单词拆分">139. 单词拆分</h2>
<p><a href="https://leetcode-cn.com/problems/word-break/" target="_blank" rel="noopener">单词拆分</a></p>
<blockquote>
<p>给定一个非空字符串 s 和一个包含非空单词的列表 wordDict，判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。</p>
<p>说明：</p>
<p>拆分时可以重复使用字典中的单词。<br>
你可以假设字典中没有重复的单词。</p>
</blockquote>
<p><code>dp[i]</code> 表示前 <code>i</code> 个元素（<code>s[0...i-1]</code>）能不能被拆分为字典中出现的单词。</p>
<p>假设当前已经知道了 <code>dp[0]、dp[1]、...、dp[i-2]</code> 的情况，现在遍历到第 <code>i</code> 个元素的时候有：</p>
<p>存在第 <code>j</code> 个元素（<code>0 ≤ j ＜ i</code>），<code>dp[i] = dp[j] &amp;&amp; check(s[j...i - 1])</code>，遍历所有 <code>j</code> 可能的取值，当能够被拆分时退出遍历即可。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">wordBreak</span><span class="params">(String s, List&lt;String&gt; wordDict)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> n = s.length();</span><br><span class="line">        <span class="keyword">boolean</span>[] dp = <span class="keyword">new</span> <span class="keyword">boolean</span>[n + <span class="number">1</span>];</span><br><span class="line">        </span><br><span class="line">        dp[<span class="number">0</span>] = <span class="keyword">true</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt;= n; i++) &#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">0</span>; j &lt; i; j++) &#123;</span><br><span class="line">                <span class="keyword">if</span> (wordDict.contains(s.substring(j, i)) &amp;&amp; dp[j]) &#123;</span><br><span class="line">                    dp[i] = <span class="keyword">true</span>;</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">return</span> dp[n];</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="下面时双序列dp">下面时双序列DP</h2>
<h2 id="1143-最长公共子序列">1143. 最长公共子序列</h2>
<p><a href="https://leetcode-cn.com/problems/longest-common-subsequence/" target="_blank" rel="noopener">最长公共子序列</a></p>
<blockquote>
<p>给定两个字符串 text1 和 text2，返回这两个字符串的最长公共子序列的长度。</p>
<p>一个字符串的 子序列 是指这样一个新的字符串：它是由原字符串在不改变字符的相对顺序的情况下删除某些字符（也可以不删除任何字符）后组成的新字符串。<br>
例如，“ace” 是 “abcde” 的子序列，但 “aec” 不是 “abcde” 的子序列。两个字符串的「公共子序列」是这两个字符串所共同拥有的子序列。</p>
<p>若这两个字符串没有公共子序列，则返回 0。</p>
</blockquote>
<p>遍历两个字符串:<br>
1、若 当前两个字符 相等：<br>
当前状态 = 两个元素的前一个状态 + 1<br>
2、若 当前两个字符 不等：<br>
当前状态 = 两个元素任一元素的前一个状态 的 最大值</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">longestCommonSubsequence</span><span class="params">(String text1, String text2)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> n = text1.length(), m = text2.length();</span><br><span class="line">        <span class="keyword">int</span>[][] dp = <span class="keyword">new</span> <span class="keyword">int</span>[n + <span class="number">1</span>][m + <span class="number">1</span>];</span><br><span class="line"></span><br><span class="line">        dp[<span class="number">0</span>][<span class="number">0</span>] = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt;= n; i++) &#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">1</span>; j &lt;= m; j++) &#123;</span><br><span class="line">                <span class="keyword">if</span> (text1.charAt(i - <span class="number">1</span>) == text2.charAt(j - <span class="number">1</span>)) &#123;</span><br><span class="line">                    dp[i][j] = dp[i - <span class="number">1</span>][j - <span class="number">1</span>] + <span class="number">1</span>;</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    dp[i][j] = Math.max(dp[i][j - <span class="number">1</span>], dp[i - <span class="number">1</span>][j]);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> dp[n][m];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="72-编辑距离">72. 编辑距离</h2>
<p><a href="https://leetcode-cn.com/problems/edit-distance/" target="_blank" rel="noopener">编辑距离</a></p>
<blockquote>
<p>给你两个单词 word1 和 word2，请你计算出将 word1 转换成 word2 所使用的最少操作数 。</p>
<p>你可以对一个单词进行如下三种操作：</p>
<p>插入一个字符<br>
删除一个字符<br>
替换一个字符</p>
</blockquote>
<p>设 <code>dp[i][j]</code> 表示 <code>word1</code> 的前 <code>i</code> 个字符(<code>word1[0, i - 1]</code>) 转换到 <code>word2</code> 的前 <code>j</code> 个字符（<code>word2[0, j - 1]</code>）所需要的次数。</p>
<p>那么状态的转移只有：</p>
<ul>
<li>插入一个字符：<code>word1=&quot;a&quot; word2=&quot;ab&quot;</code>，此时需要插入一个字符 <code>dp[i][j] = dp[i][j-1] + 1</code></li>
<li>删除一个字符：<code>word1=&quot;ab&quot; word2=&quot;a&quot;</code>，此时需要删除一个字符 <code>dp[i][j] = dp[i-1][j] + 1</code></li>
<li>替换一个字符：<code>word1=&quot;ab&quot; word2=&quot;ac&quot;</code>，此时需要替换一个字符 <code>dp[i][j] = dp[i-1][j-1] + 1</code></li>
</ul>
<p>这三种状态的转移选择其中所需要操作次数最小的去更新 <code>dp[i][j]</code>。</p>
<p>当 <code>word1[i] == word2[j]</code> 时，<code>dp[i][j] = dp[i-1][j-1]</code>。</p>
<p>且需要单独考虑 <code>word1</code> 或者 <code>word2</code> 为空的情况，此时需要对不为空的字符串中的所有字符进行操作。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">minDistance</span><span class="params">(String word1, String word2)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 分为增删改三个动作</span></span><br><span class="line">        <span class="comment">// dp[i][j] 表示 word1 的前 i 个字符转换到 word2 的前 j 个字符所需要的次数</span></span><br><span class="line">        <span class="comment">// 增：word1="a" word2="ab"，此时需要插入一个字符 dp[i][j] = dp[i][j-1] + 1</span></span><br><span class="line">        <span class="comment">// 删：word1="ab" word2="a"，此时需要删除一个字符 dp[i][j] = dp[i-1][j] + 1</span></span><br><span class="line">        <span class="comment">// 改：word1="ab" word2="ac"，此时需要替换一个字符 dp[i][j] = dp[i-1][j-1] + 1</span></span><br><span class="line">        <span class="comment">// word1 或者 word2 为空的情况单独考虑，此时需要所有元素都进行操作</span></span><br><span class="line">        <span class="comment">// 如果word1 的第 i 个字符转换到 word2 的第 j 个字符相等，那么 dp[i][j] = dp[i-1][j-1]</span></span><br><span class="line">        <span class="keyword">int</span> n = word1.length(), m = word2.length();</span><br><span class="line">      </span><br><span class="line">        </span><br><span class="line">        <span class="keyword">int</span>[][] dp = <span class="keyword">new</span> <span class="keyword">int</span>[n + <span class="number">1</span>][m + <span class="number">1</span>];</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt;= n; i++) &#123;</span><br><span class="line">            dp[i][<span class="number">0</span>] = i;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt;= m; i++) &#123;</span><br><span class="line">            dp[<span class="number">0</span>][i] = i;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt;= n ; i++) &#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">1</span>; j &lt;= m; j++) &#123;</span><br><span class="line">                </span><br><span class="line">                <span class="keyword">if</span> (word1.charAt(i - <span class="number">1</span>) == word2.charAt(j - <span class="number">1</span>)) &#123;</span><br><span class="line">                    dp[i][j] = dp[i - <span class="number">1</span>][j - <span class="number">1</span>];</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    dp[i][j] = Math.min(dp[i][j - <span class="number">1</span>], Math.min(dp[i - <span class="number">1</span>][j], dp[i - <span class="number">1</span>][j - <span class="number">1</span>])) + <span class="number">1</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> dp[n][m];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="背包和零钱兑换问题">背包和零钱兑换问题</h2>
<h2 id="322-零钱兑换">322. 零钱兑换</h2>
<p><a href="https://leetcode-cn.com/problems/coin-change/" target="_blank" rel="noopener">零钱兑换</a></p>
<blockquote>
<p>给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额，返回 -1。</p>
<p>你可以认为每种硬币的数量是无限的。</p>
</blockquote>
<p>首先定义：</p>
<ul>
<li><code>F(S)</code> 是组成金额 S 所需的最少硬币数量</li>
<li><code>[c0...cn-1]</code> 是可选的 n 枚硬币面额值</li>
</ul>
<p>假设我们知道 <code>F(S)</code>，即组成金额 S 所需最少的金币数，最后一枚硬币的面值是 C。那么可以得到转移方程：<code>F(S) = F(S-C) + 1</code></p>
<p>但是我们不知道最后一枚硬币的面值是多少，所以我们需要枚举每个硬币面额值 <code>c0,c1,...,cn-1</code> 并选择其中的最小值。<br>
$$<br>
F(S) = min \ F(S-c_{i}) + 1 \subject \  to \  S - c_{i} \geq 0<br>
$$</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">coinChange</span><span class="params">(<span class="keyword">int</span>[] coins, <span class="keyword">int</span> amount)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// F[S] = F[S-C] + 1</span></span><br><span class="line">        <span class="keyword">int</span>[] dp = <span class="keyword">new</span> <span class="keyword">int</span>[amount + <span class="number">1</span>];</span><br><span class="line">        Arrays.fill(dp, amount + <span class="number">1</span>);</span><br><span class="line">        dp[<span class="number">0</span>] = <span class="number">0</span>;</span><br><span class="line">        <span class="comment">// i 表示金额为 i</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt;= amount; i++) &#123;</span><br><span class="line">            <span class="comment">// coins[j] 表示最后一枚硬币的面额</span></span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">0</span>; j &lt; coins.length; j++) &#123;</span><br><span class="line">                <span class="comment">// i &gt;= coins[j] 能确保 i - coins[j] &gt;= 0，数组在有效范围内</span></span><br><span class="line">                <span class="keyword">if</span> (i &gt;= coins[j]) &#123;</span><br><span class="line">                    dp[i] = Math.min(dp[i], dp[i - coins[j]] + <span class="number">1</span>);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> dp[amount] &gt; amount ? -<span class="number">1</span> : dp[amount];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h1 id="8-递归">8、递归</h1>
<p>将大问题转化为小问题，通过递归依次解决各个小问题。</p>
<h2 id="24-两两交换链表中的节点">24. 两两交换链表中的节点</h2>
<p><a href="https://leetcode-cn.com/problems/swap-nodes-in-pairs/" target="_blank" rel="noopener">两两交换链表中的节点</a></p>
<p>递归的终止条件是链表中没有节点，或者链表中只有一个节点，此时无法进行交换。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> ListNode <span class="title">swapPairs</span><span class="params">(ListNode head)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (head == <span class="keyword">null</span> || head.next == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> head;</span><br><span class="line">        &#125;</span><br><span class="line">        ListNode newHead = head.next;</span><br><span class="line">        head.next = swapPairs(newHead.next);</span><br><span class="line">        newHead.next = head;</span><br><span class="line">        <span class="keyword">return</span> newHead;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="95-不同的二叉搜索树-ii">95. 不同的二叉搜索树 II</h2>
<p><a href="https://leetcode-cn.com/problems/unique-binary-search-trees-ii/" target="_blank" rel="noopener">不同的二叉搜索树 II</a></p>
<blockquote>
<p>给定一个整数 <em>n</em>，生成所有由 1 … <em>n</em> 为节点所组成的二叉搜索树。</p>
</blockquote>
<p>利用二叉搜索树的性质，如果当前二叉搜索树的根节点是 i，那么左子树是 [1, i - 1]，右子树是 [i + 1, n]。</p>
<p>利用递归解决问题，将大问题分解成为小问题。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> List&lt;TreeNode&gt; <span class="title">generateTrees</span><span class="params">(<span class="keyword">int</span> n)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (n == <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">new</span> LinkedList&lt;TreeNode&gt;();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> generateTrees(<span class="number">1</span>, n);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> List&lt;TreeNode&gt; <span class="title">generateTrees</span><span class="params">(<span class="keyword">int</span> start, <span class="keyword">int</span> end)</span> </span>&#123;</span><br><span class="line">        List&lt;TreeNode&gt; allTrees = <span class="keyword">new</span> LinkedList&lt;TreeNode&gt;();</span><br><span class="line">        <span class="keyword">if</span> (start &gt; end) &#123;</span><br><span class="line">            allTrees.add(<span class="keyword">null</span>);</span><br><span class="line">            <span class="keyword">return</span> allTrees;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 枚举可行根节点</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = start; i &lt;= end; i++) &#123;</span><br><span class="line">            <span class="comment">// 获得所有可行的左子树集合</span></span><br><span class="line">            List&lt;TreeNode&gt; leftTrees = generateTrees(start, i - <span class="number">1</span>);</span><br><span class="line"></span><br><span class="line">            <span class="comment">// 获得所有可行的右子树集合</span></span><br><span class="line">            List&lt;TreeNode&gt; rightTrees = generateTrees(i + <span class="number">1</span>, end);</span><br><span class="line"></span><br><span class="line">            <span class="comment">// 从左子树集合中选出一棵左子树，从右子树集合中选出一棵右子树，拼接到根节点上</span></span><br><span class="line">            <span class="keyword">for</span> (TreeNode left : leftTrees) &#123;</span><br><span class="line">                <span class="keyword">for</span> (TreeNode right : rightTrees) &#123;</span><br><span class="line">                    TreeNode currTree = <span class="keyword">new</span> TreeNode(i);</span><br><span class="line">                    currTree.left = left;</span><br><span class="line">                    currTree.right = right;</span><br><span class="line">                    allTrees.add(currTree);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> allTrees;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="509-斐波那契数">509. 斐波那契数</h2>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">fib</span><span class="params">(<span class="keyword">int</span> n)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (n == <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (n == <span class="number">1</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> fib(n - <span class="number">1</span>) + fib(n - <span class="number">2</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h1 id="9-滑动窗口">9、滑动窗口</h1>
<h2 id="滑动窗口模板">滑动窗口模板</h2>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">slidingWindow</span><span class="params">(String s1, String s2)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span>[] needs = <span class="keyword">new</span> <span class="keyword">int</span>[<span class="number">128</span>];</span><br><span class="line">    <span class="keyword">int</span>[] window = <span class="keyword">new</span> <span class="keyword">int</span>[<span class="number">128</span>];</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; s1.length(); i++) &#123;</span><br><span class="line">        needs[s1.charAt(i)]++;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">int</span> l = <span class="number">0</span>, r = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> count = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">while</span> (r &lt; s2.length()) &#123;</span><br><span class="line">        <span class="comment">// ch 是将移入窗口的字符</span></span><br><span class="line">        <span class="keyword">char</span> ch = s2.charAt(r);</span><br><span class="line">        <span class="comment">// 窗口内数据更新操作</span></span><br><span class="line">        ...</span><br><span class="line">        <span class="comment">// 判断左侧窗口是否需要收缩</span></span><br><span class="line">        <span class="keyword">while</span> (window needs shrink) &#123;</span><br><span class="line">            <span class="comment">// ch 是将移出窗口的字符</span></span><br><span class="line">            ch = s2.charAt(l);</span><br><span class="line">           	<span class="comment">// 窗口内数据更新操作</span></span><br><span class="line">            ...</span><br><span class="line">            <span class="comment">// 右移窗口</span></span><br><span class="line">            l++;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 右移窗口</span></span><br><span class="line">        r++;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>需要变化的地方</p>
<ol>
<li>右指针右移之后窗口数据更新</li>
<li>判断窗口是否要收缩</li>
<li>左指针右移之后窗口数据更新</li>
<li>根据题意计算结果</li>
</ol>
<h2 id="76-最小覆盖子串">76. 最小覆盖子串</h2>
<p><a href="https://leetcode-cn.com/problems/minimum-window-substring/" target="_blank" rel="noopener">最小覆盖子串</a></p>
<blockquote>
<p>给你一个字符串 <code>s</code> 、一个字符串 <code>t</code> 。返回 <code>s</code> 中涵盖 <code>t</code> 所有字符的最小子串。如果 <code>s</code> 中不存在涵盖 <code>t</code> 所有字符的子串，则返回空字符串 <code>&quot;&quot;</code> 。</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">minWindow</span><span class="params">(String s, String t)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 发现字符串的题 很多情况都是找子串问题</span></span><br><span class="line">        <span class="comment">// 问题：如何从字符串中找到目标子串</span></span><br><span class="line">        <span class="comment">// 滑动窗口</span></span><br><span class="line">        <span class="comment">// 方法：整型数组存放 Char， Char 的 int 值范围为 0 ~ 127</span></span><br><span class="line">        <span class="comment">// 利用数组 window 存放窗口中字符个数</span></span><br><span class="line">        <span class="comment">// 利用数组 needs 存放匹配子串中需要的字符个数</span></span><br><span class="line">        <span class="keyword">int</span>[] needs = <span class="keyword">new</span> <span class="keyword">int</span>[<span class="number">128</span>];</span><br><span class="line">        <span class="keyword">int</span>[] window = <span class="keyword">new</span> <span class="keyword">int</span>[<span class="number">128</span>];</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; t.length(); i++) &#123;</span><br><span class="line">            needs[t.charAt(i)]++;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">int</span> count = <span class="number">0</span>, l = <span class="number">0</span>, r = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">int</span> minLength = s.length() + <span class="number">1</span>;</span><br><span class="line">        String res = <span class="string">""</span>;</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">while</span> (r &lt; s.length()) &#123;</span><br><span class="line">            <span class="keyword">char</span> ch = s.charAt(r);</span><br><span class="line">            window[ch]++;</span><br><span class="line">            <span class="comment">// 如果字符串 t 中有字符 ch，且当前窗口中的字符 ch 数量还不够</span></span><br><span class="line">            <span class="comment">// 加等号是因为我们先做的 window[ch]++ 处理</span></span><br><span class="line">            <span class="keyword">if</span> (needs[ch] &gt; <span class="number">0</span> &amp;&amp; window[ch] &lt;= needs[ch]) &#123;</span><br><span class="line">                count++;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">// 当前窗口包含了字符串 t</span></span><br><span class="line">            <span class="comment">// 左移 l 直到不满足当前窗口包含字符串 t</span></span><br><span class="line">            <span class="keyword">while</span> (count == t.length()) &#123;</span><br><span class="line">                ch = s.charAt(l);</span><br><span class="line">                <span class="comment">// 当需要删除的字符，是必须留在窗口内的</span></span><br><span class="line">                <span class="keyword">if</span> (needs[ch] &gt; <span class="number">0</span> &amp;&amp; needs[ch] == window[ch]) &#123;</span><br><span class="line">                    count--;</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">if</span> ((r - l + <span class="number">1</span>) &lt; minLength) &#123;</span><br><span class="line">                    minLength = r - l + <span class="number">1</span>;</span><br><span class="line">                    res = s.substring(l, r + <span class="number">1</span>);</span><br><span class="line">                &#125;</span><br><span class="line">                l++;</span><br><span class="line">                window[ch]--;</span><br><span class="line">            &#125;</span><br><span class="line">            r++;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> res;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="567-字符串的排列">567. 字符串的排列</h2>
<p><a href="https://leetcode-cn.com/problems/permutation-in-string/" target="_blank" rel="noopener">字符串的排列</a></p>
<blockquote>
<p>给定两个字符串 <strong>s1</strong> 和 <strong>s2</strong>，写一个函数来判断 <strong>s2</strong> 是否包含 <strong>s1</strong> 的排列。</p>
</blockquote>
<p>滑动窗口，根据其模板修改</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">checkInclusion</span><span class="params">(String s1, String s2)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span>[] needs = <span class="keyword">new</span> <span class="keyword">int</span>[<span class="number">128</span>];</span><br><span class="line">        <span class="keyword">int</span>[] window = <span class="keyword">new</span> <span class="keyword">int</span>[<span class="number">128</span>];</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; s1.length(); i++) &#123;</span><br><span class="line">            needs[s1.charAt(i)]++;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">int</span> l = <span class="number">0</span>, r = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">int</span> count = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">while</span> (r &lt; s2.length()) &#123;</span><br><span class="line">            <span class="keyword">char</span> ch = s2.charAt(r);</span><br><span class="line">            window[ch]++;</span><br><span class="line">            <span class="keyword">if</span> (needs[ch] &gt; <span class="number">0</span> &amp;&amp; window[ch] &lt;= needs[ch]) &#123;</span><br><span class="line">                count++;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">while</span> (count == s1.length()) &#123;</span><br><span class="line">                ch = s2.charAt(l);</span><br><span class="line">                <span class="keyword">if</span> (needs[ch] &gt; <span class="number">0</span> &amp;&amp; needs[ch] == window[ch]) &#123;</span><br><span class="line">                    count--;</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="comment">// 当符合条件的最小窗口长度等于 s1 的长度</span></span><br><span class="line">                <span class="keyword">if</span> ((r - l + <span class="number">1</span>) == s1.length()) &#123;</span><br><span class="line">                    <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">                &#125;</span><br><span class="line">                l++;</span><br><span class="line">                window[ch]--;</span><br><span class="line">            &#125;</span><br><span class="line">            r++;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="483-找到字符串中所有字母异位词">483. 找到字符串中所有字母异位词</h2>
<p><a href="https://leetcode-cn.com/problems/find-all-anagrams-in-a-string/" target="_blank" rel="noopener">找到字符串中所有字母异位词</a></p>
<blockquote>
<p>给定一个字符串 <strong>s</strong> 和一个非空字符串 <strong>p</strong>，找到 <strong>s</strong> 中所有是 <strong>p</strong> 的字母异位词的子串，返回这些子串的起始索引。</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> List&lt;Integer&gt; <span class="title">findAnagrams</span><span class="params">(String s, String p)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span>[] needs = <span class="keyword">new</span> <span class="keyword">int</span>[<span class="number">128</span>];</span><br><span class="line">        <span class="keyword">int</span>[] window = <span class="keyword">new</span> <span class="keyword">int</span>[<span class="number">128</span>];</span><br><span class="line">        </span><br><span class="line">        <span class="comment">// 初始化</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; p.length(); i++) &#123;</span><br><span class="line">            needs[p.charAt(i)]++;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">int</span> l = <span class="number">0</span>, r = <span class="number">0</span>, count = <span class="number">0</span>;</span><br><span class="line">        List&lt;Integer&gt; res = <span class="keyword">new</span> ArrayList&lt;Integer&gt;();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">while</span> (r &lt; s.length()) &#123;</span><br><span class="line">            <span class="comment">// ch 是将移入窗口的字符</span></span><br><span class="line">            <span class="keyword">char</span> ch = s.charAt(r);</span><br><span class="line"></span><br><span class="line">            <span class="comment">// 窗口内数据更新操作</span></span><br><span class="line">            window[ch]++;</span><br><span class="line">            <span class="keyword">if</span> (needs[ch] &gt; <span class="number">0</span> &amp;&amp; needs[ch] &gt;= window[ch]) &#123;</span><br><span class="line">                count++;   </span><br><span class="line">            &#125;</span><br><span class="line">            </span><br><span class="line">            <span class="comment">// 判断左侧窗口是否需要收缩</span></span><br><span class="line">            <span class="keyword">while</span> (count == p.length()) &#123;</span><br><span class="line">                <span class="comment">// ch 是将移入出窗口的字符</span></span><br><span class="line">                ch = s.charAt(l);</span><br><span class="line"></span><br><span class="line">                <span class="comment">// 窗口内数据更新操作</span></span><br><span class="line">                <span class="keyword">if</span> (needs[ch] &gt; <span class="number">0</span> &amp;&amp; needs[ch] == window[ch]) &#123;</span><br><span class="line">                    count--;</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">if</span> (r - l + <span class="number">1</span> == p.length()) &#123;</span><br><span class="line">                    res.add(l);</span><br><span class="line">                &#125;</span><br><span class="line">                window[ch]--;</span><br><span class="line">                </span><br><span class="line">                <span class="comment">// 右移窗口</span></span><br><span class="line">                l++;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="comment">// 右移窗口</span></span><br><span class="line">            r++;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> res;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="3-无重复字符的最长子串">3、无重复字符的最长子串</h2>
<p><a href="(https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/)">无重复字符的最长子串</a></p>
<blockquote>
<p>给定一个字符串，请你找出其中不含有重复字符的 <strong>最长子串</strong> 的长度。</p>
</blockquote>
<p>利用 <strong>滑动窗口</strong> 来解决这个问题：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">lengthOfLongestSubstring</span><span class="params">(String s)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span>[] window = <span class="keyword">new</span> <span class="keyword">int</span>[<span class="number">128</span>];</span><br><span class="line"></span><br><span class="line">        <span class="keyword">int</span> l = <span class="number">0</span>, r = <span class="number">0</span>, count = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">int</span> maxWindow = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">while</span> (r &lt; s.length()) &#123;</span><br><span class="line">            <span class="comment">// ch 是将移入窗口的字符</span></span><br><span class="line">            <span class="keyword">char</span> ch = s.charAt(r);</span><br><span class="line"></span><br><span class="line">            <span class="comment">// 窗口内数据更新操作</span></span><br><span class="line">            <span class="comment">// 这里采取先 count++ 是因为，如果先 window[ch]++ 后</span></span><br><span class="line">            <span class="comment">// 当出现重复情况时，count 少加一次</span></span><br><span class="line">            <span class="comment">// 导致在收缩窗口的时候 count 多减了一次</span></span><br><span class="line">            <span class="keyword">if</span> (window[ch] &lt;= <span class="number">1</span>) &#123;</span><br><span class="line">                count++;</span><br><span class="line">            &#125;</span><br><span class="line">            window[ch]++;</span><br><span class="line"></span><br><span class="line">            <span class="comment">// 判断左侧窗口是否需要收缩</span></span><br><span class="line">            <span class="keyword">while</span> (window[ch] &gt; <span class="number">1</span>) &#123;</span><br><span class="line">                <span class="comment">// ch2 是将移出窗口的字符</span></span><br><span class="line">                <span class="keyword">char</span> ch2 = s.charAt(l);</span><br><span class="line">                <span class="comment">// 窗口内数据更新操作</span></span><br><span class="line">                window[ch2]--;</span><br><span class="line">                count--;</span><br><span class="line">                <span class="comment">// 右移窗口</span></span><br><span class="line">                l++;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (count &gt; maxWindow) &#123;</span><br><span class="line">                maxWindow = count;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">// 右移窗口</span></span><br><span class="line">            r++;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> maxWindow;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>利用HashSet</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">lengthOfLongestSubstring</span><span class="params">(String s)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 哈希集合，记录每个字符是否出现过</span></span><br><span class="line">        Set&lt;Character&gt; set = <span class="keyword">new</span> HashSet&lt;Character&gt;();</span><br><span class="line">        <span class="keyword">int</span> n = s.length();</span><br><span class="line">        <span class="comment">// 右指针，初始值为 -1，相当于我们在字符串的左边界的左侧，还没有开始移动</span></span><br><span class="line">        <span class="keyword">int</span> right = <span class="number">0</span>, ans = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> left = <span class="number">0</span>; left &lt; n; left++) &#123;</span><br><span class="line">            <span class="keyword">if</span> (left != <span class="number">0</span>) &#123;</span><br><span class="line">                <span class="comment">// 左指针向右移动一格，移除一个字符</span></span><br><span class="line">                set.remove(s.charAt(left - <span class="number">1</span>));</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">while</span> (right &lt; n &amp;&amp; !set.contains(s.charAt(right))) &#123;</span><br><span class="line">                <span class="comment">// 不断地移动右指针</span></span><br><span class="line">                set.add(s.charAt(right));</span><br><span class="line">                right++;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">// 第 k 到 j 个字符是一个极长的无重复字符子串</span></span><br><span class="line">            ans = Math.max(ans, set.size());</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> ans;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h1 id="10-回溯法">10、回溯法</h1>
<p>回溯法（backtrack）常用于遍历列表所有子集，是 DFS 深度搜索一种，一般用于全排列，穷尽所有可能，遍历的过程实际上是一个决策树的遍历过程。时间复杂度一般 $O(N!)$，它不像动态规划存在重叠子问题可以优化，回溯算法就是纯暴力穷举，复杂度一般都很高。</p>
<p>回溯就是类似枚举的搜索尝试过程，主要是在搜索尝试过程中寻找问题的解，当发现已不满足求解条件时，就“回溯”返回，尝试别的路径。</p>
<h2 id="回溯法模板">回溯法模板</h2>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">result = []</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">backtrack</span><span class="params">(选择列表,路径)</span>:</span></span><br><span class="line"><span class="function">    <span class="title">if</span> <span class="params">(满足结束条件)</span>:</span></span><br><span class="line"><span class="function">        result.<span class="title">add</span><span class="params">(路径)</span></span>;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    <span class="keyword">for</span> 选择 in 选择列表:</span><br><span class="line">        做选择;</span><br><span class="line">        backtrack(选择列表,路径);</span><br><span class="line">        撤销选择;</span><br><span class="line">        backtrack(选择列表,路径);</span><br></pre></td></tr></table></figure>
<p>做选择的时候，找<strong>子集</strong>从 i 开始 for 循环，找<strong>排列组合</strong>从 0 开始 for 循环。</p>
<p><strong>总结：回溯类题一定要考虑的几个方面</strong></p>
<ul>
<li><strong>有效结果：当长度为输入长度的时候停止，并保存当前结果</strong></li>
<li><strong>回溯条件：每一层都是全部元素遍历</strong></li>
<li><strong>剪枝条件：要用check数组来保存用过的元素，用过的不能再用了，这是回溯里面的一个重要考虑因素</strong></li>
</ul>
<h2 id="78-子集">78.  子集</h2>
<p><a href="https://leetcode-cn.com/problems/subsets/" target="_blank" rel="noopener">子集</a></p>
<blockquote>
<p>给你一个整数数组 <code>nums</code> ，返回该数组所有可能的子集（幂集）。解集不能包含重复的子集。</p>
</blockquote>
<p><strong>方法一：</strong> 逐个枚举，空集的幂集只有空集，每增加一个元素，让之前幂集中的每个集合，追加这个元素，就是新增的子集。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> List&lt;List&lt;Integer&gt;&gt; enumerate(<span class="keyword">int</span>[] nums) &#123;</span><br><span class="line">    List&lt;List&lt;Integer&gt;&gt; res = <span class="keyword">new</span> ArrayList&lt;List&lt;Integer&gt;&gt;();</span><br><span class="line">    res.add(<span class="keyword">new</span> ArrayList&lt;Integer&gt;());</span><br><span class="line">    <span class="keyword">for</span> (Integer n : nums) &#123;</span><br><span class="line">        <span class="keyword">int</span> size = res.size();</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; size; i++) &#123;</span><br><span class="line">            List&lt;Integer&gt; newSub = <span class="keyword">new</span> ArrayList&lt;Integer&gt;(res.get(i));</span><br><span class="line">            newSub.add(n);</span><br><span class="line">            res.add(newSub);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> res;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>方法二：</strong> 二进制位标记选取子集，枚举 $mask ∈ [0, 2^{n}-1]$ ，标记不同的位组成不同的子集。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="keyword">public</span> List&lt;List&lt;Integer&gt;&gt; subsets(<span class="keyword">int</span>[] nums) &#123;</span><br><span class="line">        List&lt;List&lt;Integer&gt;&gt; res = <span class="keyword">new</span> ArrayList&lt;List&lt;Integer&gt;&gt;();</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> mask = <span class="number">0</span>; mask &lt; (<span class="number">1</span> &lt;&lt; nums.length); mask++) &#123;</span><br><span class="line">            List newSub = <span class="keyword">new</span> ArrayList&lt;Integer&gt;();</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; nums.length; i++) &#123;</span><br><span class="line">                <span class="comment">// 比较当前位置是否要取</span></span><br><span class="line">                <span class="keyword">if</span> ((mask &amp; (<span class="number">1</span> &lt;&lt; i)) != <span class="number">0</span>) &#123;</span><br><span class="line">                    newSub.add(nums[i]);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            res.add(newSub);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> res;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>方法三：</strong> 回溯。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    List&lt;List&lt;Integer&gt;&gt; res = <span class="keyword">new</span> ArrayList&lt;List&lt;Integer&gt;&gt;();</span><br><span class="line">    <span class="keyword">public</span> List&lt;List&lt;Integer&gt;&gt; subsets(<span class="keyword">int</span>[] nums) &#123;</span><br><span class="line">        backtrack(nums, <span class="keyword">new</span> ArrayList&lt;Integer&gt;(), <span class="number">0</span>);</span><br><span class="line">        <span class="keyword">return</span> res;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">backtrack</span><span class="params">(<span class="keyword">int</span>[] nums, List&lt;Integer&gt; list, <span class="keyword">int</span> i)</span> </span>&#123;</span><br><span class="line">        res.add(<span class="keyword">new</span> ArrayList&lt;Integer&gt;(list));</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> j = i; j &lt; nums.length; j++) &#123;</span><br><span class="line">            list.add(nums[j]);</span><br><span class="line">            backtrack(nums, list, j + <span class="number">1</span>);</span><br><span class="line">            list.remove(list.size() - <span class="number">1</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="90-子集-ii">90. 子集 II</h2>
<p><a href="https://leetcode-cn.com/problems/subsets-ii/" target="_blank" rel="noopener">子集 II</a></p>
<blockquote>
<p>给定一个可能包含重复元素的整数数组 <strong><em>nums</em></strong>，返回该数组所有可能的子集（幂集）。</p>
<p>**说明：**解集不能包含重复的子集。</p>
</blockquote>
<p>排序后，关键点在于画出递归树（排列树），然后观察如何去重：<strong>我们要去重的是同一树层上的“使用过”，同一树枝上的都是一个组合里的元素，不用去重</strong>。</p>
<p><img src="https://pic.tyzhang.top/images/2021/01/19/42618258fec183614b260c226836310c4cbd86787e143ce27285464d501ec46e-QQE688AAE59BBE20200608123027.png" alt="42618258fec183614b260c226836310c4cbd86787e143ce27285464d501ec46e-QQE688AAE59BBE20200608123027.png">如果 <code>nums[j]</code> 是在同层的在<strong>for循环里重复出现</strong>的，那么 j 肯定大于 i，否则比较的两个元素就处于不同层</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    List&lt;List&lt;Integer&gt;&gt; res = <span class="keyword">new</span> ArrayList&lt;List&lt;Integer&gt;&gt;();</span><br><span class="line">    List&lt;Integer&gt; tempList = <span class="keyword">new</span> ArrayList&lt;Integer&gt;();</span><br><span class="line">    <span class="keyword">public</span> List&lt;List&lt;Integer&gt;&gt; subsetsWithDup(<span class="keyword">int</span>[] nums) &#123;</span><br><span class="line">        Arrays.sort(nums);</span><br><span class="line">        backtrack(nums, <span class="number">0</span>);</span><br><span class="line">        <span class="keyword">return</span> res;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">backtrack</span><span class="params">(<span class="keyword">int</span>[] nums, <span class="keyword">int</span> i)</span> </span>&#123;</span><br><span class="line">        res.add(<span class="keyword">new</span> ArrayList&lt;Integer&gt;(tempList));</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> j = i; j &lt; nums.length; j++) &#123;</span><br><span class="line">            <span class="keyword">if</span> (j &gt; i &amp;&amp; nums[j] == nums[j - <span class="number">1</span>]) <span class="keyword">continue</span>;</span><br><span class="line">            tempList.add(nums[j]);</span><br><span class="line">            backtrack(nums, j + <span class="number">1</span>);</span><br><span class="line">            tempList.remove(tempList.size() - <span class="number">1</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="46-全排列">46. 全排列</h2>
<p><a href="https://leetcode-cn.com/problems/permutations/" target="_blank" rel="noopener">全排列</a></p>
<blockquote>
<p>给定一个 <strong>没有重复</strong> 数字的序列，返回其所有可能的全排列。</p>
</blockquote>
<p>套用回溯法模板的同时，画出递归树来完善代码逻辑，判断是否解决问题。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    List&lt;List&lt;Integer&gt;&gt; res = <span class="keyword">new</span> ArrayList&lt;List&lt;Integer&gt;&gt;();</span><br><span class="line">    List&lt;Integer&gt; tempList = <span class="keyword">new</span> ArrayList&lt;Integer&gt;();</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">public</span> List&lt;List&lt;Integer&gt;&gt; permute(<span class="keyword">int</span>[] nums) &#123;</span><br><span class="line">        backtrack(nums, <span class="number">0</span>, <span class="keyword">new</span> <span class="keyword">boolean</span>[nums.length]);</span><br><span class="line">        <span class="keyword">return</span> res;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">backtrack</span><span class="params">(<span class="keyword">int</span>[] nums, <span class="keyword">int</span> i, <span class="keyword">boolean</span>[] visited)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (i == nums.length) &#123;</span><br><span class="line">            res.add(<span class="keyword">new</span> ArrayList&lt;Integer&gt;(tempList));</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">0</span>; j &lt; nums.length; j++) &#123;</span><br><span class="line">            <span class="keyword">if</span> (visited[j] == <span class="keyword">true</span>) &#123;</span><br><span class="line">                <span class="keyword">continue</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            visited[j] = <span class="keyword">true</span>;</span><br><span class="line">            tempList.add(nums[j]);</span><br><span class="line">            backtrack(nums, i + <span class="number">1</span>, visited);</span><br><span class="line">            visited[j] = <span class="keyword">false</span>;</span><br><span class="line">            tempList.remove(tempList.size() - <span class="number">1</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="47-全排列-ii">47. 全排列 II</h2>
<p><a href="https://leetcode-cn.com/problems/permutations-ii/" target="_blank" rel="noopener">全排列 II</a></p>
<blockquote>
<p>给定一个可包含重复数字的序列 <code>nums</code> ，<strong>按任意顺序</strong> 返回所有不重复的全排列。</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    List&lt;List&lt;Integer&gt;&gt; res = <span class="keyword">new</span> ArrayList&lt;List&lt;Integer&gt;&gt;();</span><br><span class="line">    List&lt;Integer&gt; tempList = <span class="keyword">new</span> ArrayList&lt;Integer&gt;();</span><br><span class="line">    <span class="keyword">public</span> List&lt;List&lt;Integer&gt;&gt; permuteUnique(<span class="keyword">int</span>[] nums) &#123;</span><br><span class="line">        backtrack(nums, <span class="number">0</span>, <span class="keyword">new</span> <span class="keyword">boolean</span>[nums.length]);</span><br><span class="line">        <span class="keyword">return</span> res;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">backtrack</span><span class="params">(<span class="keyword">int</span>[] nums, <span class="keyword">int</span> i, <span class="keyword">boolean</span>[] visited)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (i == nums.length) &#123;</span><br><span class="line">            res.add(<span class="keyword">new</span> ArrayList&lt;Integer&gt;(tempList));</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// start[] 数组用于去重</span></span><br><span class="line">        <span class="keyword">boolean</span>[] start = <span class="keyword">new</span> <span class="keyword">boolean</span>[<span class="number">22</span>];</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">0</span>; j &lt; nums.length; j++) &#123;</span><br><span class="line">            <span class="keyword">if</span> (visited[j] == <span class="keyword">true</span> || start[nums[j] + <span class="number">10</span>] == <span class="keyword">true</span>) &#123;</span><br><span class="line">                <span class="keyword">continue</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            visited[j] = <span class="keyword">true</span>;</span><br><span class="line">            start[nums[j] + <span class="number">10</span>] = <span class="keyword">true</span>;</span><br><span class="line">            tempList.add(nums[j]);</span><br><span class="line">            backtrack(nums, i + <span class="number">1</span>, visited);</span><br><span class="line">            visited[j] = <span class="keyword">false</span>;</span><br><span class="line">            tempList.remove(tempList.size() - <span class="number">1</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="39-组合总数">39. 组合总数</h2>
<p><a href="https://leetcode-cn.com/problems/combination-sum/" target="_blank" rel="noopener">组合总和</a></p>
<blockquote>
<p>给定一个无重复元素的数组 candidates 和一个目标数 target ，找出 candidates 中所有可以使数字和为 target 的组合。</p>
<p>candidates 中的数字可以无限制重复被选取。</p>
</blockquote>
<p>如何限制不产生重复组合？</p>
<p>只要限制下一次选择的起点，是基于本次的选择，这样下一次就不会选到本次选择的同层左边的数。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    List&lt;List&lt;Integer&gt;&gt; res = <span class="keyword">new</span> ArrayList&lt;List&lt;Integer&gt;&gt;();</span><br><span class="line">    List&lt;Integer&gt; tempList = <span class="keyword">new</span> ArrayList&lt;Integer&gt;();</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> List&lt;List&lt;Integer&gt;&gt; combinationSum(<span class="keyword">int</span>[] candidates, <span class="keyword">int</span> target) &#123;</span><br><span class="line">        backtrack(candidates, <span class="number">0</span>, <span class="number">0</span>, target);</span><br><span class="line">        <span class="keyword">return</span> res;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">backtrack</span><span class="params">(<span class="keyword">int</span>[] candidates, <span class="keyword">int</span> start, <span class="keyword">int</span> sum, <span class="keyword">int</span> target)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (sum == target) &#123;</span><br><span class="line">            res.add(<span class="keyword">new</span> ArrayList&lt;Integer&gt;(tempList));</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = start; i &lt; candidates.length; i++) &#123;</span><br><span class="line">            <span class="keyword">if</span> (sum + candidates[i] &gt; target) &#123;</span><br><span class="line">                <span class="keyword">continue</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            tempList.add(candidates[i]);</span><br><span class="line">            <span class="comment">// i 从 start 开始是因为元素可以重复选择</span></span><br><span class="line">            <span class="comment">// 且能够限制下一层递归是从当前元素开始，不会出现重复选择之前的元素，造成解集重复</span></span><br><span class="line">            backtrack(candidates, i, sum + candidates[i], target);</span><br><span class="line">            tempList.remove(tempList.size() - <span class="number">1</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="17-电话号码的字母组合">17. 电话号码的字母组合</h2>
<p><a href="https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number/" target="_blank" rel="noopener">电话号码的字母组合</a></p>
<blockquote>
<p>给定一个仅包含数字 <code>2-9</code> 的字符串，返回所有它能表示的字母组合。</p>
</blockquote>
<p>回溯法穷举所有可能的组合。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="keyword">char</span>[][] dict = &#123;</span><br><span class="line">        &#123;<span class="string">'a'</span>, <span class="string">'b'</span>, <span class="string">'c'</span>&#125;,</span><br><span class="line">        &#123;<span class="string">'d'</span>, <span class="string">'e'</span>, <span class="string">'f'</span>&#125;,</span><br><span class="line">        &#123;<span class="string">'g'</span>, <span class="string">'h'</span>, <span class="string">'i'</span>&#125;,</span><br><span class="line">        &#123;<span class="string">'j'</span>, <span class="string">'k'</span>, <span class="string">'l'</span>&#125;,</span><br><span class="line">        &#123;<span class="string">'m'</span>, <span class="string">'n'</span>, <span class="string">'o'</span>&#125;,</span><br><span class="line">        &#123;<span class="string">'p'</span>, <span class="string">'q'</span>, <span class="string">'r'</span>, <span class="string">'s'</span>&#125;,</span><br><span class="line">        &#123;<span class="string">'t'</span>, <span class="string">'u'</span>, <span class="string">'v'</span>&#125;,</span><br><span class="line">        &#123;<span class="string">'w'</span>, <span class="string">'x'</span>, <span class="string">'y'</span>, <span class="string">'z'</span>&#125;</span><br><span class="line">    &#125;;</span><br><span class="line">    List&lt;String&gt; res = <span class="keyword">new</span> ArrayList&lt;String&gt;();</span><br><span class="line">    StringBuffer tempString = <span class="keyword">new</span> StringBuffer();</span><br><span class="line">    <span class="function"><span class="keyword">public</span> List&lt;String&gt; <span class="title">letterCombinations</span><span class="params">(String digits)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (digits.length() == <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> res;</span><br><span class="line">        &#125;</span><br><span class="line">        backtrack(digits, <span class="number">0</span>);</span><br><span class="line">        <span class="keyword">return</span> res;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">backtrack</span><span class="params">(String digits, <span class="keyword">int</span> i)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (i == digits.length()) &#123;</span><br><span class="line">            res.add(tempString.toString());</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 当前数字对应对应字典的下标</span></span><br><span class="line">        <span class="keyword">int</span> index = digits.charAt(i) - <span class="string">'2'</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">0</span>; j &lt; dict[index].length; j++) &#123;</span><br><span class="line">            tempString.append(dict[index][j]);</span><br><span class="line">            backtrack(digits, i + <span class="number">1</span>);</span><br><span class="line">            tempString.deleteCharAt(i);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="131-分割回文串">131. 分割回文串</h2>
<p><a href="https://leetcode-cn.com/problems/palindrome-partitioning/" target="_blank" rel="noopener">分割回文串</a></p>
<blockquote>
<p>给定一个字符串 <em>s</em>，将 <em>s</em> 分割成一些子串，使每个子串都是回文串。</p>
<p>返回 <em>s</em> 所有可能的分割方案。</p>
</blockquote>
<p>切割问题，类似组合问题。例如对于字符串 <code>abcdef</code>：</p>
<ul>
<li>组合问题：选取一个 <code>a</code> 之后，在 <code>bcdef</code> 中再去选取第二个，选取 <code>b</code>之后在 <code>cdef</code> 中在选组第三个…</li>
<li>切割问题：切割一个 <code>a</code> 之后，在 <code>bcdef</code> 中再去切割第二段，切割 <code>b</code> 之后在 <code>cdef</code> 中在切割第三段…</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    List&lt;List&lt;String&gt;&gt; res = <span class="keyword">new</span> ArrayList&lt;List&lt;String&gt;&gt;();</span><br><span class="line">    List&lt;String&gt; tempList = <span class="keyword">new</span> ArrayList&lt;String&gt;();</span><br><span class="line">    <span class="keyword">public</span> List&lt;List&lt;String&gt;&gt; partition(String s) &#123;</span><br><span class="line">        backtrack(s, <span class="number">0</span>);</span><br><span class="line">        <span class="keyword">return</span> res;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">backtrack</span><span class="params">(String s, <span class="keyword">int</span> i)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (i == s.length()) &#123;</span><br><span class="line">            res.add(<span class="keyword">new</span> ArrayList&lt;String&gt;(tempList));</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 回溯所有分割方案</span></span><br><span class="line">        <span class="comment">// 只有当前 s[i] 到 s[j] 能够被分割成回文串才能算作一次有效分割</span></span><br><span class="line">        <span class="comment">// 那么在此基础上，继续往后寻找可能的分割方案 </span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> j = i; j &lt; s.length(); j++) &#123;</span><br><span class="line">            <span class="keyword">if</span> (check(s.substring(i, j + <span class="number">1</span>))) &#123;</span><br><span class="line">                tempList.add(s.substring(i, j + <span class="number">1</span>));</span><br><span class="line">                backtrack(s, j + <span class="number">1</span>);</span><br><span class="line">                tempList.remove(tempList.size() - <span class="number">1</span>);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">check</span><span class="params">(String s)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> n = s.length();</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; n / <span class="number">2</span>; i++) &#123;</span><br><span class="line">            <span class="keyword">if</span> (s.charAt(i) != s.charAt(n - <span class="number">1</span> - i)) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="93-复原ip地址">93. 复原IP地址</h2>
<p><a href="https://leetcode-cn.com/problems/restore-ip-addresses/" target="_blank" rel="noopener">复原IP地址</a></p>
<blockquote>
<p>给定一个只包含数字的字符串，复原它并返回所有可能的 IP 地址格式。</p>
</blockquote>
<p>同样的自己画个树形图分析问题，可以利用 IP 地址的规则来剪枝：</p>
<ul>
<li>字符串长度在 4 到 12 之间；</li>
<li>IP 地址的一个段只可能是 3 位，最大为 255；</li>
<li>每个段只有 3 种截取方法：截 1 位、截 2 位、截 3 位；</li>
<li>由于 IP 地址 4 个段，所以这颗树最多 4 层。</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    List&lt;String&gt; res = <span class="keyword">new</span> ArrayList&lt;String&gt;();</span><br><span class="line">    List&lt;String&gt; tempStr = <span class="keyword">new</span> ArrayList&lt;String&gt;();</span><br><span class="line">    <span class="function"><span class="keyword">public</span> List&lt;String&gt; <span class="title">restoreIpAddresses</span><span class="params">(String s)</span> </span>&#123;</span><br><span class="line">        backtrack(s, <span class="number">0</span>, <span class="number">0</span>);</span><br><span class="line">        <span class="keyword">return</span> res;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// index 标记现在分割到了第几段</span></span><br><span class="line">    <span class="comment">// i 表示字符串被分割到了第几位</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">backtrack</span><span class="params">(String s, <span class="keyword">int</span> i, <span class="keyword">int</span> index)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (index &gt; <span class="number">4</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (index == <span class="number">4</span> &amp;&amp; i == s.length()) &#123;</span><br><span class="line">            StringBuffer sb = <span class="keyword">new</span> StringBuffer(); </span><br><span class="line">            sb.append(tempStr.get(<span class="number">0</span>));</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> k = <span class="number">1</span>; k &lt; tempStr.size(); k++) &#123;</span><br><span class="line">                sb.append(<span class="string">"."</span> + tempStr.get(k));</span><br><span class="line">            &#125;</span><br><span class="line">            res.add(sb.toString());</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// j - i &lt;= 3 表示 IP 地址的一个整数最多是三位</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> j = i; j - i &lt;= <span class="number">3</span> &amp;&amp; j &lt; s.length(); j++) &#123;</span><br><span class="line">            <span class="keyword">if</span> (!check(s.substring(i, j + <span class="number">1</span>))) &#123;</span><br><span class="line">                <span class="keyword">continue</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            </span><br><span class="line">            tempStr.add(s.substring(i, j + <span class="number">1</span>));</span><br><span class="line">            backtrack(s, j + <span class="number">1</span>, index + <span class="number">1</span>);</span><br><span class="line">            tempStr.remove(tempStr.size() - <span class="number">1</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; </span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">check</span><span class="params">(String s)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> n = s.length();</span><br><span class="line">        <span class="comment">// 去除 0 开头的情况</span></span><br><span class="line">        <span class="keyword">if</span> (n &gt; <span class="number">1</span> &amp;&amp; s.charAt(<span class="number">0</span>) == <span class="string">'0'</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">int</span> num = Integer.valueOf(s);</span><br><span class="line">        <span class="keyword">if</span> (num &lt;= <span class="number">255</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h1 id="11-初级算法">11、初级算法</h1>
<h2 id="1-数组">1、数组</h2>
<h3 id="26-删除排序数组中的重复项">26. 删除排序数组中的重复项</h3>
<blockquote>
<p>给定一个排序数组，你需要在 原地 删除重复出现的元素，使得每个元素只出现一次，返回移除后数组的新长度。<br>
不要使用额外的数组空间，你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。</p>
</blockquote>
<p>使用双指针</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">class Solution &#123;</span><br><span class="line">    public int removeDuplicates(int[] nums) &#123;</span><br><span class="line">        int k = 0;</span><br><span class="line">        for (int i = 1; i &lt; nums.length; i++) &#123;</span><br><span class="line">            if (nums[i] != nums[k]) &#123;</span><br><span class="line">                k++;</span><br><span class="line">                nums[k] = nums[i];</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        return k + 1;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="122-买卖股票的最佳时机-ii">122. 买卖股票的最佳时机 II</h3>
<p><a href="https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/" target="_blank" rel="noopener">买卖股票的最佳时机 II</a></p>
<blockquote>
<p>给定一个数组，它的第 i 个元素是一支给定股票第 i 天的价格。<br>
设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易（多次买卖一支股票）。<br>
注意：你不能同时参与多笔交易（你必须在再次购买前出售掉之前的股票）。</p>
</blockquote>
<p>贪心，观察买卖股票收益即卖出价格减去买入价格，那么每次股票收益为正时都算到收益当中，加起来就是最大收益。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">maxProfit</span><span class="params">(<span class="keyword">int</span>[] prices)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> n = prices.length, res = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">int</span>[] priceDifference = <span class="keyword">new</span> <span class="keyword">int</span>[n - <span class="number">1</span>];</span><br><span class="line">        <span class="comment">// 每天的股价差值</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; n - <span class="number">1</span>; i++) &#123;</span><br><span class="line">            priceDifference[i] = prices[i + <span class="number">1</span>] - prices[i]; </span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 把所有正的股价差相加</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; n - <span class="number">1</span>; i++) &#123;</span><br><span class="line">            <span class="keyword">if</span> (priceDifference[i] &gt; <span class="number">0</span>) &#123;</span><br><span class="line">                res += priceDifference[i];</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> res;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="189-旋转数组">189. 旋转数组</h3>
<p><a href="https://leetcode-cn.com/problems/rotate-array/" target="_blank" rel="noopener">旋转数组</a></p>
<blockquote>
<p>给定一个数组，将数组中的元素向右移动 <code>k</code> 个位置，其中 <code>k</code> 是非负数。</p>
</blockquote>
<p>当我们将数组的元素向右移动 k 次后，尾部 k mod n 个元素会移动至数组头部，其余元素向后移动 k mod n 个位置。</p>
<p>数组的翻转：我们可以先将所有元素翻转，这样尾部的 k mod  n 个元素就被移至数组头部，然后我们再翻转 [0, k mod n-1] 区间的元素和 [k mod n, n-1] 区间的元素即能得到最后的答案。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">rotate</span><span class="params">(<span class="keyword">int</span>[] nums, <span class="keyword">int</span> k)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> n = nums.length;</span><br><span class="line">        k %= n;</span><br><span class="line">        reverse(nums, <span class="number">0</span>, n - <span class="number">1</span>);</span><br><span class="line">        reverse(nums, <span class="number">0</span>, k - <span class="number">1</span>);</span><br><span class="line">        reverse(nums, k, n - <span class="number">1</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">reverse</span><span class="params">(<span class="keyword">int</span>[] nums, <span class="keyword">int</span> l, <span class="keyword">int</span> r)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> temp = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">while</span> (l &lt; r) &#123;</span><br><span class="line">            temp = nums[l];</span><br><span class="line">            nums[l] = nums[r];</span><br><span class="line">            nums[r] = temp;</span><br><span class="line">            l++;</span><br><span class="line">            r--;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="217-存在重复元素">217. 存在重复元素</h3>
<p><a href="https://leetcode-cn.com/problems/contains-duplicate/" target="_blank" rel="noopener">存在重复元素</a></p>
<blockquote>
<p>给定一个整数数组，判断是否存在重复元素。</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">containsDuplicate</span><span class="params">(<span class="keyword">int</span>[] nums)</span> </span>&#123;</span><br><span class="line">        Set&lt;Integer&gt; set = <span class="keyword">new</span> HashSet&lt;Integer&gt;(nums.length);</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> num : nums) &#123;</span><br><span class="line">            <span class="keyword">if</span> (!set.add(num)) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="350-两个数组的交集-ii">350. 两个数组的交集 II</h3>
<p><a href="https://leetcode-cn.com/problems/intersection-of-two-arrays-ii/" target="_blank" rel="noopener">两个数组的交集 II</a></p>
<blockquote>
<p>给定两个数组，编写一个函数来计算它们的交集。</p>
</blockquote>
<p>由于同一个数字在两个数组中都可能出现多次，因此需要用哈希表存储每个数字出现的次数。对于一个数字，其在交集中出现的次数等于该数字在两个数组中出现次数的最小值。</p>
<p>为了降低空间复杂度，首先遍历较短的数组并在哈希表中记录每个数字以及对应出现的次数，然后遍历较长的数组得到交集。(这里我的代码并没有去实现)</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">int</span>[] intersect(<span class="keyword">int</span>[] nums1, <span class="keyword">int</span>[] nums2) &#123;</span><br><span class="line">        Map&lt;Integer, Integer&gt; map = <span class="keyword">new</span> HashMap&lt;Integer, Integer&gt;();</span><br><span class="line">        <span class="keyword">int</span>[] res = <span class="keyword">new</span> <span class="keyword">int</span>[Math.max(nums1.length, nums2.length)];</span><br><span class="line">        <span class="keyword">int</span> p = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> num : nums1) &#123;</span><br><span class="line">            map.put(num, map.getOrDefault(num, <span class="number">0</span>) + <span class="number">1</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> num : nums2) &#123;</span><br><span class="line">            Integer temp = map.get(num);</span><br><span class="line">            <span class="keyword">if</span> (temp != <span class="keyword">null</span> &amp;&amp; temp &gt; <span class="number">0</span>) &#123;</span><br><span class="line">                res[p++] = num;</span><br><span class="line">                map.put(num, --temp);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> Arrays.copyOf(res, p);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="283-移动零">283. 移动零</h3>
<p><a href="https://leetcode-cn.com/problems/move-zeroes/" target="_blank" rel="noopener">移动零</a></p>
<blockquote>
<p>给定一个数组 <code>nums</code>，编写一个函数将所有 <code>0</code> 移动到数组的末尾，同时保持非零元素的相对顺序。</p>
</blockquote>
<p>非 0 往前挪，剩下的补 0。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">moveZeroes</span><span class="params">(<span class="keyword">int</span>[] nums)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> k = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; nums.length; i++) &#123;</span><br><span class="line">            <span class="keyword">if</span> (nums[i] == <span class="number">0</span>) &#123;</span><br><span class="line">                k++;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                nums[i - k] = nums[i];</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt;= k; i++) &#123;</span><br><span class="line">            nums[nums.length - i] = <span class="number">0</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>双指针</strong></p>
<p>使用双指针，左指针指向当前已经处理好的序列的尾部，右指针指向待处理序列的头部。</p>
<p>右指针不断向右移动，每次右指针指向非零数，则将左右指针对应的数交换，同时左指针右移。</p>
<p>注意到以下性质：</p>
<ul>
<li>左指针左边均为非零数；</li>
<li>右指针左边直到左指针处均为零。</li>
</ul>
<p>因此每次交换，都是将左指针的零与右指针的非零数交换，且非零数的相对顺序并未改变。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">moveZeroes</span><span class="params">(<span class="keyword">int</span>[] nums)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> n = nums.length, left = <span class="number">0</span>, right = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">while</span> (right &lt; n) &#123;</span><br><span class="line">            <span class="keyword">if</span> (nums[right] != <span class="number">0</span>) &#123;</span><br><span class="line">                swap(nums, left, right);</span><br><span class="line">                left++;</span><br><span class="line">            &#125;</span><br><span class="line">            right++;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">swap</span><span class="params">(<span class="keyword">int</span>[] nums, <span class="keyword">int</span> left, <span class="keyword">int</span> right)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> temp = nums[left];</span><br><span class="line">        nums[left] = nums[right];</span><br><span class="line">        nums[right] = temp;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="1-两数之和">1. 两数之和</h3>
<p><a href="https://leetcode-cn.com/problems/two-sum/" target="_blank" rel="noopener">两数之和</a></p>
<blockquote>
<p>给定一个整数数组 <code>nums</code> 和一个整数目标值 <code>target</code>，请你在该数组中找出 <strong>和为目标值</strong> 的那 <strong>两个</strong> 整数，并返回它们的数组下标。</p>
</blockquote>
<p>使用哈希表，可以将寻找 <code>target - x</code> 的时间复杂度降低到从 O*(*N) 降低到 O(1)。</p>
<p>这样我们创建一个哈希表，对于每一个 <code>x</code>，我们首先查询哈希表中是否存在 <code>target - x</code>，然后将 <code>x</code> 插入到哈希表中，即可保证不会让 <code>x</code> 和自己匹配。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">int</span>[] twoSum(<span class="keyword">int</span>[] nums, <span class="keyword">int</span> target) &#123;</span><br><span class="line">        Map&lt;Integer, Integer&gt; hashtable = <span class="keyword">new</span> HashMap&lt;Integer, Integer&gt;();</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; nums.length; i++) &#123;</span><br><span class="line">            <span class="keyword">if</span> (hashtable.containsKey(target - nums[i])) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">new</span> <span class="keyword">int</span>[] &#123;hashtable.get(target - nums[i]), i&#125;;</span><br><span class="line">            &#125;</span><br><span class="line">            hashtable.put(nums[i], i);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="keyword">int</span>[<span class="number">0</span>];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="36-有效的数独">36. 有效的数独</h3>
<p><a href="https://leetcode-cn.com/problems/valid-sudoku/" target="_blank" rel="noopener">有效的数独</a></p>
<blockquote>
<p>判断一个 9x9 的数独是否有效。</p>
</blockquote>
<p>行和列都可以一次迭代完成，如何确保能一次迭代完成枚举子数独呢？</p>
<p>可以使用 <code>box = (row / 3) * 3 + col / 3</code>，这样将 9 个子数独从左到右从上到下划分为 0 ~ 8 共 9 个子数独。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isValidSudoku</span><span class="params">(<span class="keyword">char</span>[][] board)</span> </span>&#123;</span><br><span class="line">        Map&lt;Integer, Integer&gt;[] rowMap = <span class="keyword">new</span> HashMap[<span class="number">9</span>];</span><br><span class="line">        Map&lt;Integer, Integer&gt;[] colMap = <span class="keyword">new</span> HashMap[<span class="number">9</span>];</span><br><span class="line">        Map&lt;Integer, Integer&gt;[] boxMap = <span class="keyword">new</span> HashMap[<span class="number">9</span>];</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">9</span>; i++) &#123;</span><br><span class="line">            rowMap[i] = <span class="keyword">new</span> HashMap&lt;Integer, Integer&gt;(<span class="number">9</span>);</span><br><span class="line">            colMap[i] = <span class="keyword">new</span> HashMap&lt;Integer, Integer&gt;(<span class="number">9</span>);</span><br><span class="line">            boxMap[i] = <span class="keyword">new</span> HashMap&lt;Integer, Integer&gt;(<span class="number">9</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">9</span>; i++) &#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">0</span>; j &lt; <span class="number">9</span>; j++) &#123;</span><br><span class="line">                <span class="keyword">if</span> (board[i][j] == <span class="string">'.'</span>) &#123;</span><br><span class="line">                    <span class="keyword">continue</span>;</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">int</span> num = (<span class="keyword">int</span>) board[i][j];</span><br><span class="line">                <span class="keyword">int</span> box = (i / <span class="number">3</span>) * <span class="number">3</span> + j / <span class="number">3</span>;</span><br><span class="line">                <span class="comment">// 更新 map</span></span><br><span class="line">                rowMap[i].put(num, rowMap[i].getOrDefault(num, <span class="number">0</span>) + <span class="number">1</span>);</span><br><span class="line">                colMap[j].put(num, colMap[j].getOrDefault(num, <span class="number">0</span>) + <span class="number">1</span>);</span><br><span class="line">                boxMap[box].put(num, boxMap[box].getOrDefault(num, <span class="number">0</span>) + <span class="number">1</span>);</span><br><span class="line">                <span class="comment">// 检查是否满足条件</span></span><br><span class="line">                <span class="keyword">if</span> (rowMap[i].get(num) &gt; <span class="number">1</span> || colMap[j].get(num) &gt; <span class="number">1</span> || boxMap[box].get(num) &gt; <span class="number">1</span>) &#123;</span><br><span class="line">                    <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="48-旋转图像">48. 旋转图像</h3>
<p><a href="https://leetcode-cn.com/problems/rotate-image/" target="_blank" rel="noopener">旋转图像</a></p>
<blockquote>
<p>给定一个 <em>n</em> × <em>n</em> 的二维矩阵表示一个图像。<br>
将图像顺时针旋转 90 度。</p>
</blockquote>
<p>先以对角线（左上&lt;—&gt;右下）为轴进行翻转，再对每行左右翻转即可。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">rotate</span><span class="params">(<span class="keyword">int</span>[][] matrix)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 先以对角线（左上&lt;—&gt;右下）为轴进行翻转，再对每行左右翻转即可。</span></span><br><span class="line">        <span class="keyword">int</span> n = matrix.length;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; n; i++) &#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> j = i + <span class="number">1</span>; j &lt; n; j++) &#123;</span><br><span class="line">                <span class="keyword">int</span> temp = matrix[i][j]; </span><br><span class="line">                matrix[i][j] = matrix[j][i];</span><br><span class="line">                matrix[j][i] = temp;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; n; i++) &#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">0</span>; j &lt; n / <span class="number">2</span>; j++) &#123;</span><br><span class="line">                <span class="keyword">int</span> temp = matrix[i][j];</span><br><span class="line">                matrix[i][j] = matrix[i][n - j - <span class="number">1</span>];</span><br><span class="line">                matrix[i][n - j - <span class="number">1</span>] = temp;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="2-字符串">2、字符串</h2>
<h3 id="387字符串中的第一个唯一字符">387.字符串中的第一个唯一字符</h3>
<p><a href="https://leetcode-cn.com/problems/first-unique-character-in-a-string/" target="_blank" rel="noopener">字符串中的第一个唯一字符</a></p>
<blockquote>
<p>给定一个字符串，找到它的第一个不重复的字符，并返回它的索引。如果不存在，则返回 -1。</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">firstUniqChar</span><span class="params">(String s)</span> </span>&#123;</span><br><span class="line">        Map&lt;Character, Integer&gt; map = <span class="keyword">new</span> HashMap&lt;Character, Integer&gt;();</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; s.length(); i++) &#123;</span><br><span class="line">            <span class="keyword">char</span> ch = s.charAt(i);</span><br><span class="line">            map.put(ch, map.getOrDefault(ch, <span class="number">0</span>) + <span class="number">1</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (map.containsValue(<span class="number">1</span>)) &#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; s.length(); i++) &#123;</span><br><span class="line">                <span class="keyword">char</span> ch = s.charAt(i);</span><br><span class="line">                <span class="keyword">if</span> (map.get(ch) == <span class="number">1</span>) &#123;</span><br><span class="line">                    <span class="keyword">return</span> i;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> -<span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>另解：</strong> 维护一个队列，队头一定是只出现一次的字符</p>
<h3 id="242-有效的字母异位词">242. 有效的字母异位词</h3>
<p><a href="https://leetcode-cn.com/problems/valid-anagram/" target="_blank" rel="noopener">有效的字母异位词</a></p>
<blockquote>
<p>给定两个字符串 <em>s</em> 和 <em>t</em> ，编写一个函数来判断 <em>t</em> 是否是 <em>s</em> 的字母异位词。</p>
</blockquote>
<p>哈希映射，更新字符出现的次数，最后遍历整个哈希表判断是否都为 0。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isAnagram</span><span class="params">(String s, String t)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> n = s.length(), m = t.length();</span><br><span class="line">        <span class="keyword">if</span> (n != m) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        Map&lt;Character, Integer&gt; map = <span class="keyword">new</span> HashMap&lt;Character, Integer&gt;();</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; n; i++) &#123;</span><br><span class="line">            <span class="keyword">char</span> ch = s.charAt(i);</span><br><span class="line">            map.put(ch, map.getOrDefault(ch, <span class="number">0</span>) + <span class="number">1</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; m; i++) &#123;</span><br><span class="line">            <span class="keyword">char</span> ch = t.charAt(i);</span><br><span class="line">            <span class="keyword">int</span> freq = map.getOrDefault(ch, <span class="number">0</span>);</span><br><span class="line">            <span class="keyword">if</span> (freq == <span class="number">0</span>) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            map.put(ch, freq - <span class="number">1</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> freq : map.values()) &#123;</span><br><span class="line">            <span class="keyword">if</span> (freq &gt; <span class="number">0</span>) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="125-验证回文串">125. 验证回文串</h3>
<p><a href="https://leetcode-cn.com/problems/valid-palindrome/" target="_blank" rel="noopener">验证回文串</a></p>
<blockquote>
<p>给定一个字符串，验证它是否是回文串，只考虑字母和数字字符，可以忽略字母的大小写。</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isPalindrome</span><span class="params">(String s)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> n = s.length();</span><br><span class="line">        <span class="keyword">int</span> l = <span class="number">0</span>, r = n - <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">while</span> (l &lt; r) &#123;</span><br><span class="line">            <span class="keyword">while</span> (l &lt; r &amp;&amp; !Character.isLetterOrDigit(s.charAt(l))) &#123;</span><br><span class="line">                l++;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">while</span> (l &lt; r &amp;&amp; !Character.isLetterOrDigit(s.charAt(r))) &#123;</span><br><span class="line">                r--;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (l &lt; r) &#123;</span><br><span class="line">                <span class="keyword">if</span> (Character.toLowerCase(s.charAt(l)) != Character.toLowerCase(s.charAt(r))) &#123;</span><br><span class="line">                    <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">                &#125;</span><br><span class="line">                l++;</span><br><span class="line">                r--;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="38-外观数列">38. 外观数列</h3>
<p><a href="https://leetcode-cn.com/problems/count-and-say/" target="_blank" rel="noopener">外观数列</a></p>
<blockquote>
<p>给定一个正整数 <code>n</code> ，输出外观数列的第 <code>n</code> 项。「外观数列」是一个整数序列，从数字 1 开始，序列中的每一项都是对前一项的描述。</p>
</blockquote>
<p><strong>普通解法</strong></p>
<p>模拟该行为</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">countAndSay</span><span class="params">(<span class="keyword">int</span> n)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (n == <span class="number">1</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="string">"1"</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        String sub = countAndSay(n - <span class="number">1</span>);</span><br><span class="line">        StringBuffer sb = <span class="keyword">new</span> StringBuffer();</span><br><span class="line">        <span class="keyword">char</span> ch = sub.charAt(<span class="number">0</span>);</span><br><span class="line">        <span class="keyword">int</span> times = <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt; sub.length(); i++) &#123;</span><br><span class="line">            <span class="keyword">if</span> (sub.charAt(i) != ch) &#123;</span><br><span class="line">                sb.append(times);</span><br><span class="line">                sb.append(ch);</span><br><span class="line">                ch = sub.charAt(i);</span><br><span class="line">                times = <span class="number">1</span>;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                times++;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 解决末尾的阶段</span></span><br><span class="line">        sb.append(times);</span><br><span class="line">        sb.append(ch);</span><br><span class="line">        <span class="keyword">return</span> sb.toString();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>优化，添加哨兵</strong> 哨兵可以使我们不用在循环外处理边界</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">countAndSay</span><span class="params">(<span class="keyword">int</span> n)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (n == <span class="number">1</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="string">"1"</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        String sub = countAndSay(n - <span class="number">1</span>);</span><br><span class="line">        <span class="comment">// 添加哨兵</span></span><br><span class="line">        sub = sub + <span class="string">"a"</span>;</span><br><span class="line">        StringBuffer sb = <span class="keyword">new</span> StringBuffer();</span><br><span class="line">        <span class="keyword">char</span> ch = sub.charAt(<span class="number">0</span>);</span><br><span class="line">        <span class="keyword">int</span> times = <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt; sub.length(); i++) &#123;</span><br><span class="line">            <span class="keyword">if</span> (sub.charAt(i) != ch) &#123;</span><br><span class="line">                sb.append(times);</span><br><span class="line">                sb.append(ch);</span><br><span class="line">                ch = sub.charAt(i);</span><br><span class="line">                times = <span class="number">1</span>;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                times++;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> sb.toString();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="3-链表">3、链表</h2>
<h4 id="237-删除链表中的节点">237. 删除链表中的节点</h4>
<p><a href="https://leetcode-cn.com/problems/delete-node-in-a-linked-list/" target="_blank" rel="noopener">删除链表中的节点</a></p>
<blockquote>
<p>请编写一个函数，使其可以删除某个链表中给定的（非末尾）节点。传入函数的唯一参数为 <strong>要被删除的节点</strong> 。</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">deleteNode</span><span class="params">(ListNode node)</span> </span>&#123;</span><br><span class="line">        node.val = node.next.val;</span><br><span class="line">        node.next = node.next.next;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="19-删除链表的倒数第-n-个节点">19. 删除链表的倒数第 N 个节点</h3>
<p><a href="https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/" target="_blank" rel="noopener">删除链表的倒数第 N 个结点</a></p>
<blockquote>
<p>给你一个链表，删除链表的倒数第 <code>n</code> 个结点，并且返回链表的头结点。</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> ListNode <span class="title">removeNthFromEnd</span><span class="params">(ListNode head, <span class="keyword">int</span> n)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 小技巧，pre的下一个指针指向head，这样遍历到需要的位置时，pre就是需要的节点的前节点</span></span><br><span class="line">        ListNode  preNode = <span class="keyword">new</span> ListNode(<span class="number">0</span>, head);</span><br><span class="line">        ListNode curNode = preNode, tempNode = preNode;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; n ; i++) &#123;</span><br><span class="line">            curNode = curNode.next;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">while</span> (curNode.next != <span class="keyword">null</span>) &#123;</span><br><span class="line">            curNode = curNode.next;</span><br><span class="line">            tempNode = tempNode.next;</span><br><span class="line">        &#125;</span><br><span class="line">        tempNode.next = tempNode.next.next;</span><br><span class="line">        <span class="comment">// 不返回head，是因为head有可能是被删掉的节点</span></span><br><span class="line">        <span class="keyword">return</span> preNode.next;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="234-回文链表">234. 回文链表</h3>
<p><a href="https://leetcode-cn.com/problems/palindrome-linked-list/" target="_blank" rel="noopener">回文链表</a></p>
<blockquote>
<p>请判断一个链表是否为回文链表。</p>
</blockquote>
<p>用到了反转链表和快慢指针。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isPalindrome</span><span class="params">(ListNode head)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (head == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 找到前半部分链表的尾节点并反转后半部分链表</span></span><br><span class="line">        ListNode firstHalfEnd = endOfFirstHalf(head);</span><br><span class="line">        ListNode secondHalfStart = reverseList(firstHalfEnd.next);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 判断是否回文</span></span><br><span class="line">        ListNode p1 = head;</span><br><span class="line">        ListNode p2 = secondHalfStart;</span><br><span class="line">        <span class="keyword">boolean</span> result = <span class="keyword">true</span>;</span><br><span class="line">        <span class="keyword">while</span> (result &amp;&amp; p2 != <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">if</span> (p1.val != p2.val) &#123;</span><br><span class="line">                result = <span class="keyword">false</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            p1 = p1.next;</span><br><span class="line">            p2 = p2.next;</span><br><span class="line">        &#125;        </span><br><span class="line"></span><br><span class="line">        <span class="comment">// 还原链表并返回结果</span></span><br><span class="line">        firstHalfEnd.next = reverseList(secondHalfStart);</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> ListNode <span class="title">reverseList</span><span class="params">(ListNode head)</span> </span>&#123;</span><br><span class="line">        ListNode prev = <span class="keyword">null</span>;</span><br><span class="line">        ListNode curr = head;</span><br><span class="line">        <span class="keyword">while</span> (curr != <span class="keyword">null</span>) &#123;</span><br><span class="line">            ListNode nextTemp = curr.next;</span><br><span class="line">            curr.next = prev;</span><br><span class="line">            prev = curr;</span><br><span class="line">            curr = nextTemp;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> prev;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> ListNode <span class="title">endOfFirstHalf</span><span class="params">(ListNode head)</span> </span>&#123;</span><br><span class="line">        ListNode fast = head;</span><br><span class="line">        ListNode slow = head;</span><br><span class="line">        <span class="keyword">while</span> (fast.next != <span class="keyword">null</span> &amp;&amp; fast.next.next != <span class="keyword">null</span>) &#123;</span><br><span class="line">            fast = fast.next.next;</span><br><span class="line">            slow = slow.next;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> slow;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h1 id="无序刷题">无序刷题</h1>
<h2 id="3-无重复字符的最长子串">3、无重复字符的最长子串</h2>
<p><a href="(https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/)">无重复字符的最长子串</a></p>
<blockquote>
<p>给定一个字符串，请你找出其中不含有重复字符的 <strong>最长子串</strong> 的长度。</p>
</blockquote>
<p>利用 <strong>滑动窗口</strong> 来解决这个问题：</p>
<ul>
<li>用两个指针left，right来分别指向滑动窗口的左端和右端，即某个字串的开始位置和结束位置；</li>
<li>每步操作都将左指针往右挪一位，表示枚举下一个字符为起始位置，然后不断地右移右指针，但需要确保滑动窗口中没有重复字符。移动结束后，记录该窗口的长度即不含有重复字符的子串的长度；</li>
<li>枚举结束后，找到最长的子串的长度即为答案。</li>
</ul>
<p><strong>判断重复字符</strong></p>
<p>使用哈希集合（Java中的HashSet）来帮助我们判断是否有重复的字符。左指针右移时，从哈希集合中移除一个字符，右指针右移时，向哈希集合中添加一个字符。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">lengthOfLongestSubstring</span><span class="params">(String s)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 哈希集合，记录每个字符是否出现过</span></span><br><span class="line">        Set&lt;Character&gt; set = <span class="keyword">new</span> HashSet&lt;Character&gt;();</span><br><span class="line">        <span class="keyword">int</span> n = s.length();</span><br><span class="line">        <span class="comment">// 右指针，初始值为 -1，相当于我们在字符串的左边界的左侧，还没有开始移动</span></span><br><span class="line">        <span class="keyword">int</span> right = <span class="number">0</span>, ans = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> left = <span class="number">0</span>; left &lt; n; left++) &#123;</span><br><span class="line">            <span class="keyword">if</span> (left != <span class="number">0</span>) &#123;</span><br><span class="line">                <span class="comment">// 左指针向右移动一格，移除一个字符</span></span><br><span class="line">                set.remove(s.charAt(left - <span class="number">1</span>));</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">while</span> (right &lt; n &amp;&amp; !set.contains(s.charAt(right))) &#123;</span><br><span class="line">                <span class="comment">// 不断地移动右指针</span></span><br><span class="line">                set.add(s.charAt(right));</span><br><span class="line">                right++;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">// 第 k 到 j 个字符是一个极长的无重复字符子串</span></span><br><span class="line">            ans = Math.max(ans, set.size());</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> ans;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="4-寻找两个正序数组的中位数">4、寻找两个正序数组的中位数</h2>
<p><a href="https://leetcode-cn.com/problems/median-of-two-sorted-arrays/" target="_blank" rel="noopener">寻找两个正序数组的中位数</a></p>
<blockquote>
<p>给定两个大小为 m 和 n 的正序（从小到大）数组 <code>nums1</code> 和 <code>nums2</code> 。</p>
<p>请你找出这两个正序数组的中位数，并且要求算法的时间复杂度为 O(log(m + n))。</p>
</blockquote>
<p><strong>暴力解法</strong> 只需要每次取 <code>nums1</code> 和 <code>nums2</code> 中较小的那个数，一直取到中文数的位置再进行计算即可，时间复杂度是 O(m+n)，达不到题目要求。</p>
<p><strong>二分查找</strong> 将问题中的求中位数，转换成为 <strong>求第k小数</strong> 的特殊情况。假设我们要找第 <code>k</code> 小的数，每次循环排除掉 <code>k/2</code> 个数。看下面的例子，比如要找第 <code>7</code> 小的数字。</p>
<ul>
<li>$k=7,k/2=3$</li>
<li>数组<code>A</code>：(1,3,<strong>4</strong>),9</li>
<li>数组<code>B</code>：(1,2,<strong>3</strong>),4,5,6,7,8,9,10</li>
</ul>
<p>比较两个数组的第 <code>k/2</code> 个数字（向下取整），也就是比较第 <strong>3</strong> 个数字，数组<code>A</code>中的 <strong>4</strong> 和数组<code>B</code>中的 <strong>3</strong> ，因为 <strong>3</strong> 比 <strong>4</strong> 小，所以可以表明数组 <code>B</code> 的前 <code>k/2</code> 个数字都不是第 <code>k</code> 个数字。也就是说 <strong>1,2,3</strong> 这三个数字不可能是第 <strong>7</strong> 小的数字，我们可以将它们给排除掉。然后将数组 <code>A</code> 和排除掉前 <code>k/2</code> 个数字的数组 <code>B</code> 重新比较，直到找第 <code>1</code> 小的数字，只需要判断两个数组中第一个数字哪个小就可以了。</p>
<p><strong>总结</strong></p>
<ul>
<li>设 <code>(n+m)</code> 为两个数组合起来的长度，那么不论奇数还是偶数，我们 <strong>求第k小的数字</strong> 都可以通过计算第$(n+m+1)/2$和$(n+m+2)/2$个数字来解决。
<ul>
<li>当 <code>(n+m)</code> 是偶数时，两数相加除以2即可得到中位数；</li>
<li>当 <code>(n+m)</code> 是奇数时，计算了两次中位数，也应该是两数相加除以2。</li>
</ul>
</li>
<li>当 <code>nums1[k/2]</code> 小于 <code>nums2[k/2]</code> 时，丢掉 <code>nums1[]</code> 的前 <code>k/2</code> 个数字；</li>
<li>当 <code>nums1[k/2]</code> 大于等于 <code>nums2[k/2]</code> 时，丢掉 <code>nums2[]</code> 的前 <code>k/2</code>个数字；</li>
<li>当其中一个数组的长度为 <strong>0</strong> 时，只需要求另一个数组的第 <strong>k</strong> 小的数字；</li>
<li>当k = 1时，求两个数组第一个数字中较小的那个；</li>
<li>当 <code>k/2</code> 超过数组长度时，取数组最后一个数字即可。</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">double</span> <span class="title">findMedianSortedArrays</span><span class="params">(<span class="keyword">int</span>[] nums1, <span class="keyword">int</span>[] nums2)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> n = nums1.length;</span><br><span class="line">        <span class="keyword">int</span> m = nums2.length;</span><br><span class="line">        <span class="keyword">int</span> left = (n + m + <span class="number">1</span>) / <span class="number">2</span>;</span><br><span class="line">        <span class="keyword">int</span> right = (n + m + <span class="number">2</span>) / <span class="number">2</span>;</span><br><span class="line">        <span class="comment">// 当n+m为偶数时，应该计算 (left+right)/2</span></span><br><span class="line">        <span class="comment">// 当n+m为奇数时，计算了两次中位数，也应该是 (left+right)/2</span></span><br><span class="line">        <span class="comment">// 于是不论是奇数还是偶数，都可以用一套代码解决</span></span><br><span class="line">        <span class="keyword">return</span> (getKth(nums1, <span class="number">0</span>, n - <span class="number">1</span>, nums2, <span class="number">0</span>, m - <span class="number">1</span>, left) + getKth(nums1, <span class="number">0</span>, n - <span class="number">1</span>, nums2, <span class="number">0</span>, m - <span class="number">1</span>, right)) / <span class="number">2.0</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">getKth</span><span class="params">(<span class="keyword">int</span>[] nums1, <span class="keyword">int</span> start1, <span class="keyword">int</span> end1, <span class="keyword">int</span>[] nums2, <span class="keyword">int</span> start2, <span class="keyword">int</span> end2, <span class="keyword">int</span> k)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> len1 = end1 - start1 + <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">int</span> len2 = end2 - start2 + <span class="number">1</span>;</span><br><span class="line">        </span><br><span class="line">        <span class="comment">// 确保 nums1[] 一定比 nums2[] 短</span></span><br><span class="line">        <span class="comment">// 当有空的数组出现时，一定是 nums1[]</span></span><br><span class="line">        <span class="keyword">if</span>(len1 &gt; len2) &#123;</span><br><span class="line">            <span class="keyword">return</span> getKth(nums2, start2, end2, nums1, start1, end1, k);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span>(len1 == <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> nums2[start2 + k - <span class="number">1</span>];</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (k == <span class="number">1</span>) <span class="keyword">return</span> Math.min(nums1[start1], nums2[start2]);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">int</span> i = start1 + Math.min(len1, k / <span class="number">2</span>) - <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">int</span> j = start2 + Math.min(len2, k / <span class="number">2</span>) - <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span>(nums1[i] &lt; nums2[j]) &#123;</span><br><span class="line">            <span class="keyword">return</span> getKth(nums1, i + <span class="number">1</span>, end1, nums2, start2, end2, k - (i - start1 + <span class="number">1</span>));</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> getKth(nums1, start1, end1, nums2, j + <span class="number">1</span>, end2, k - (j - start2 + <span class="number">1</span>));</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="7-整数反转">7、 整数反转</h2>
<p><a href="https://leetcode-cn.com/problems/reverse-integer/" target="_blank" rel="noopener">整数反转</a></p>
<blockquote>
<p>给出一个 32 位的有符号整数，你需要将这个整数中每位上的数字进行反转。比如输入 <code>123</code> 输出 <code>321</code> ，输入 <code>120</code> 输出 <code>21</code> ，输入 <code>-123</code>输 出 <code>-321</code> 。</p>
<p>假设我们的环境只能存储得下 32 位的有符号整数，则其数值范围为$ [−2^{31},  2^{31} − 1]$。请根据这个假设，如果反转后整数溢出那么就返回 0。</p>
</blockquote>
<p>主要是注意溢出问题。重复取出 <code>x</code> 的最后一位数字，并将它放到 <code>res</code> 的后面。最后 <code>res</code> 将与 <code>x</code> 相反。</p>
<p>这种方法在 <code>temp = res * 10 + pop</code> 时会有溢出风险。我们假设 <code>res</code> 是一个正数。</p>
<ul>
<li>如果 <code>temp = res * 10 + pop</code> 导致溢出，那么一定有res &gt;= INTMAX/10​</li>
<li>如果res &gt; INTMAX / 10​，那么 <code>temp = res * 10 + pop</code> 一定会溢出</li>
<li>如果res == INTMAX / 10，那么只要 <code>pop</code> 大于 INTMAX % 10​， <code>temp = res * 10 + pop</code> 就会溢出</li>
</ul>
<p>当 <code>res</code> 为负时可以应用同样的逻辑。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">reverse</span><span class="params">(<span class="keyword">int</span> x)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> res = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">int</span> mag = <span class="number">10</span>;</span><br><span class="line">        <span class="keyword">while</span> (x != <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="keyword">if</span> (res &gt; Integer.MAX_VALUE / <span class="number">10</span> || (res == Integer.MAX_VALUE / <span class="number">10</span> &amp;&amp; x % <span class="number">10</span> &gt; Integer.MAX_VALUE % <span class="number">10</span>)) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (res &lt; Integer.MIN_VALUE / <span class="number">10</span> || (res == Integer.MIN_VALUE / <span class="number">10</span> &amp;&amp; x % <span class="number">10</span> &lt; Integer.MIN_VALUE % <span class="number">10</span>)) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            res = res * mag + x % <span class="number">10</span>;</span><br><span class="line">            x = x / <span class="number">10</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> res;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="10-正则表达式匹配">10. 正则表达式匹配</h2>
<p><a href="https://leetcode-cn.com/problems/regular-expression-matching/" target="_blank" rel="noopener">正则表达式匹配</a></p>
<blockquote>
<p>给你一个字符串 <code>s</code> 和一个字符规律 <code>p</code>，请你来实现一个支持 <code>'.'</code> 和 <code>'*'</code> 的正则表达式匹配。</p>
<p><code>'.'</code> 匹配任意单个字符<br>
<code>'*'</code> 匹配零个或多个前面的那一个元素<br>
所谓匹配，是要涵盖 <strong>整个</strong> 字符串 <code>s</code> 的，而不是部分字符串。</p>
<p>说明:</p>
<p><code>s</code> 可能为空，且只包含从 <code>a-z</code> 的小写字母。<br>
<code>p</code> 可能为空，且只包含从 <code>a-z</code> 的小写字母，以及字符 <code>.</code> 和 <code>*</code>。</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isMatch</span><span class="params">(String text, String pattern)</span> </span>&#123;</span><br><span class="line">    	<span class="comment">// 如果都为空则匹配成功，text不空pattern空匹配失败</span></span><br><span class="line">        <span class="keyword">if</span> (pattern.isEmpty()) &#123;</span><br><span class="line">            <span class="keyword">return</span> text.isEmpty();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 第一个是否匹配上</span></span><br><span class="line">        <span class="keyword">boolean</span> first_match = (!text.isEmpty() &amp;&amp; (pattern.charAt(<span class="number">0</span>) == text.charAt(<span class="number">0</span>) || pattern.charAt(<span class="number">0</span>) == <span class="string">'.'</span>));</span><br><span class="line">        </span><br><span class="line">        <span class="comment">// 只有长度大于2的时候才考虑'*''</span></span><br><span class="line">        <span class="keyword">if</span> (pattern.length() &gt;= <span class="number">2</span> &amp;&amp; pattern.charAt(<span class="number">1</span>) == <span class="string">'*'</span>) &#123;</span><br><span class="line">            <span class="comment">// 看有没有可能,剩下的pattern匹配上全部的text</span></span><br><span class="line">            <span class="comment">// 看有没有可能,剩下的text匹配整个pattern</span></span><br><span class="line">            <span class="comment">// isMatch(text, pattern.substring(2)) 指当p第二个为*时，前面的字符不影响匹配所以可以忽略，所以将*以及*之前的一个字符删除后匹配之后的字符，这就是为什么用pattern.substring(2)</span></span><br><span class="line">            <span class="comment">// pattern 直接跳过两个字符，表示 * 前边的字符出现0次</span></span><br><span class="line">            <span class="comment">//如果第一个已经匹配成功，并且第二个字符为*时，这是我们就要判断之后的需要匹配的字符串是否是多个前面的元素（*的功能），这就是first_match &amp;&amp; isMatch(text.substring(1), pattern))的意义</span></span><br><span class="line">            <span class="comment">// pattern 不变，例如 text = aa，pattern = a*，第一个 a 匹配，然后 text 的第二个 a 接着和 pattern 的第一个 a 进行匹配。表示 * 用前一个字符替代</span></span><br><span class="line">            <span class="keyword">return</span> (isMatch(text, pattern.substring(<span class="number">2</span>)) || (first_match &amp;&amp; isMatch(text.substring(<span class="number">1</span>), pattern)));</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="comment">// 没有星星的情况:第一个字符相等,而且剩下的text,匹配上剩下的pattern，没有星星且第一个匹配成功，那么s和p同时向右移动一位看是否仍然能匹配成功</span></span><br><span class="line">            <span class="keyword">return</span> first_match &amp;&amp; isMatch(text.substring(<span class="number">1</span>), pattern.substring(<span class="number">1</span>));</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="13-罗马数字转整数">13. 罗马数字转整数</h2>
<p><a href="https://leetcode-cn.com/problems/roman-to-integer/" target="_blank" rel="noopener">罗马数字转整数</a></p>
<blockquote>
<p>罗马数字转整数，例如 <code>&quot;III&quot;</code> 转为 <code>3</code> ，<code>&quot;IV&quot;</code> 转为 <code>4</code> ，<code>&quot;VI&quot;</code> 转为 <code>6</code>，可以观察到如果前面的小于后面的是减法 <code>&quot;IV&quot;</code> = <code>V</code> - <code>I</code> ，前面大于后面是加法 <code>&quot;VI&quot;</code> = <code>V</code> + <code>I</code>。</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">romanToInt</span><span class="params">(String s)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> sum = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">int</span> preNum = getValue(s.charAt(<span class="number">0</span>));</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">1</span>;i &lt; s.length(); i ++) &#123;</span><br><span class="line">            <span class="keyword">int</span> num = getValue(s.charAt(i));</span><br><span class="line">            <span class="keyword">if</span>(preNum &lt; num) &#123;</span><br><span class="line">                sum -= preNum;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                sum += preNum;</span><br><span class="line">            &#125;</span><br><span class="line">            preNum = num;</span><br><span class="line">        &#125;</span><br><span class="line">        sum += preNum;</span><br><span class="line">        <span class="keyword">return</span> sum;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">int</span> <span class="title">getValue</span><span class="params">(<span class="keyword">char</span> ch)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">switch</span>(ch) &#123;</span><br><span class="line">            <span class="keyword">case</span> <span class="string">'I'</span>: <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">            <span class="keyword">case</span> <span class="string">'V'</span>: <span class="keyword">return</span> <span class="number">5</span>;</span><br><span class="line">            <span class="keyword">case</span> <span class="string">'X'</span>: <span class="keyword">return</span> <span class="number">10</span>;</span><br><span class="line">            <span class="keyword">case</span> <span class="string">'L'</span>: <span class="keyword">return</span> <span class="number">50</span>;</span><br><span class="line">            <span class="keyword">case</span> <span class="string">'C'</span>: <span class="keyword">return</span> <span class="number">100</span>;</span><br><span class="line">            <span class="keyword">case</span> <span class="string">'D'</span>: <span class="keyword">return</span> <span class="number">500</span>;</span><br><span class="line">            <span class="keyword">case</span> <span class="string">'M'</span>: <span class="keyword">return</span> <span class="number">1000</span>;</span><br><span class="line">            <span class="keyword">default</span>: <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="14-最长公共前缀">14. 最长公共前缀</h2>
<p><a href="https://leetcode-cn.com/problems/longest-common-prefix/" target="_blank" rel="noopener">最长公共前缀</a></p>
<p><strong>纵向挨个比较</strong></p>
<p>从第一个字符开始比较，遇到不相同或者某个字符串到末尾了结束。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">longestCommonPrefix</span><span class="params">(String[] strs)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span>(strs == <span class="keyword">null</span> || strs.length == <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="string">""</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">int</span> point = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">while</span> (point &lt; strs[<span class="number">0</span>].length()) &#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt; strs.length; i++) &#123;</span><br><span class="line">                <span class="keyword">if</span> (point &gt;= strs[i].length()) &#123;</span><br><span class="line">                    <span class="comment">// 超出某个字符串的长度，那么以当前长度为最长公共前缀</span></span><br><span class="line">                    <span class="keyword">return</span> strs[<span class="number">0</span>].substring(<span class="number">0</span>, point);</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">if</span> (strs[<span class="number">0</span>].charAt(point) != strs[i].charAt(point)) &#123;</span><br><span class="line">                    <span class="comment">// 如果当前位置的字符不相同，那么前面的是最长公共前缀</span></span><br><span class="line">                    <span class="keyword">return</span> strs[<span class="number">0</span>].substring(<span class="number">0</span>, point);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            point++;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 比较完了整个strs[0]，它就是最长公共前缀</span></span><br><span class="line">        <span class="keyword">return</span> strs[<span class="number">0</span>];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>二分查找</strong></p>
<p>每次取查找范围的中间值 <code>mid</code>，判断每个字符串的长度为 <code>mid</code> 的前缀是否相同，如果相同则最长公共前缀的长度一定大于或等于 <code>mid</code>，如果不相同则最长公共前缀的长度一定小于 <code>mid</code>。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">longestCommonPrefix</span><span class="params">(String[] strs)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (strs == <span class="keyword">null</span> || strs.length == <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="string">""</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">int</span> minLength = Integer.MAX_VALUE;</span><br><span class="line">        <span class="keyword">for</span> (String str : strs) &#123;</span><br><span class="line">            minLength = Math.min(minLength, str.length());</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">int</span> left = <span class="number">0</span>, right = minLength;</span><br><span class="line">        <span class="keyword">while</span> (left &lt; right) &#123;</span><br><span class="line">            <span class="keyword">int</span> mid = left + (right - left + <span class="number">1</span>) / <span class="number">2</span>;</span><br><span class="line">            <span class="keyword">if</span> (isCommonPre(strs, mid)) &#123;</span><br><span class="line">                left = mid;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                right = mid - <span class="number">1</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> strs[<span class="number">0</span>].substring(<span class="number">0</span>, left);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">boolean</span> <span class="title">isCommonPre</span><span class="params">(String[] strs, <span class="keyword">int</span> mid)</span> </span>&#123;</span><br><span class="line">        String commonPre = strs[<span class="number">0</span>].substring(<span class="number">0</span>, mid);</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt; strs.length; i++) &#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">0</span>; j &lt; mid; j++) &#123;</span><br><span class="line">                <span class="keyword">if</span> (commonPre.charAt(j) != strs[i].charAt(j)) &#123;</span><br><span class="line">                    <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="66-加一">66. 加一</h2>
<p><a href="https://leetcode-cn.com/problems/plus-one/" target="_blank" rel="noopener">加一</a></p>
<blockquote>
<p>给定一个由 整数 组成的 非空 数组所表示的非负整数，在该数的基础上加一。</p>
<p>最高位数字存放在数组的首位， 数组中每个元素只存储单个数字。</p>
<p>你可以假设除了整数 0 之外，这个整数不会以零开头。</p>
</blockquote>
<p>加一只可能出现两种情况：</p>
<ul>
<li>该位数字为 <code>0~8</code>，加一即可；</li>
<li>该位数字为 <code>9</code>，进位并将该位置为 <code>0</code>。</li>
</ul>
<p>于是我们可以从数组的末尾即个位开始判断，如果不需要进位，则直接个位加 1 返回整个数组；如果需要进位则将该位置 0，接着去处理更高位，直到处理完最高位。</p>
<p>特殊情况如 99，处理完最高位后还需要进位，那么需要手动的进行扩充数组进位。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">int</span>[] plusOne(<span class="keyword">int</span>[] digits) &#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = digits.length - <span class="number">1</span>; i &gt;= <span class="number">0</span>; i--) &#123;</span><br><span class="line">            digits[i]++;</span><br><span class="line">            digits[i] = digits[i] % <span class="number">10</span>;</span><br><span class="line">            <span class="keyword">if</span> (digits[i] != <span class="number">0</span>) &#123;</span><br><span class="line">                <span class="keyword">return</span> digits;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (digits[<span class="number">0</span>] == <span class="number">0</span>) &#123;</span><br><span class="line">            digits = <span class="keyword">new</span> <span class="keyword">int</span>[digits.length + <span class="number">1</span>];</span><br><span class="line">            digits[<span class="number">0</span>] = <span class="number">1</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> digits;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="334-反转字符串">334. 反转字符串</h2>
<p><a href="https://leetcode-cn.com/problems/reverse-string/" target="_blank" rel="noopener">反转字符串</a></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">class Solution &#123;</span><br><span class="line">    public void reverseString(char[] s) &#123;</span><br><span class="line">        int n = s.length;</span><br><span class="line">        for (int i = 0; i &lt; n / 2; i++) &#123;</span><br><span class="line">            char temp = s[i];</span><br><span class="line">            s[i] = s[n - 1 - i];</span><br><span class="line">            s[n - 1 - i] = temp;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="213-打家劫舍ii">213. 打家劫舍II</h2>
<p><a href="https://leetcode-cn.com/problems/house-robber-ii/" target="_blank" rel="noopener">打家劫舍 II</a></p>
<p>一个数组，相邻的不能同时选择，头和尾不能同时选择，求最大和。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">rob</span><span class="params">(<span class="keyword">int</span>[] nums)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 总共n间房，从0开始计数，第一间和最后一间不能同时偷，转换为两个case</span></span><br><span class="line">        <span class="comment">// 1) 不偷第一间，那么就是在 [1,n-1] 之间的最大值</span></span><br><span class="line">        <span class="comment">// 2) 不偷最后一件，那么就是在 [0,n-2] 之间的最大值</span></span><br><span class="line">        <span class="comment">// 状态转移方程： dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1])，含义是投最后一间和不偷最后一间</span></span><br><span class="line">        </span><br><span class="line">        <span class="keyword">if</span> (nums.length == <span class="number">1</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> nums[<span class="number">0</span>];</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (nums.length == <span class="number">2</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> Math.max(nums[<span class="number">0</span>], nums[<span class="number">1</span>]);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 优化，因为整个过程中只需要用到 dp[i-1] 和 dp[i-2] 即可，因此可以优化为两个变量去记录</span></span><br><span class="line">        <span class="keyword">int</span> n = nums.length;</span><br><span class="line">        <span class="comment">// [0,n-2]</span></span><br><span class="line">        <span class="keyword">int</span> rangeA = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">int</span> first = nums[<span class="number">0</span>], second = Math.max(nums[<span class="number">0</span>], nums[<span class="number">1</span>]);</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">2</span>; i &lt;= n - <span class="number">2</span>; i++) &#123;</span><br><span class="line">            <span class="keyword">int</span> temp = Math.max(first + nums[i], second);</span><br><span class="line">            first = second;</span><br><span class="line">            second = temp;</span><br><span class="line">        &#125;</span><br><span class="line">        rangeA = second;</span><br><span class="line">        <span class="comment">// [1,n-1]</span></span><br><span class="line">        <span class="keyword">int</span> rangeB = <span class="number">0</span>;</span><br><span class="line">        first = nums[<span class="number">1</span>];</span><br><span class="line">        second = Math.max(nums[<span class="number">1</span>], nums[<span class="number">2</span>]);</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">3</span>; i &lt;= n - <span class="number">1</span>; i++) &#123;</span><br><span class="line">            <span class="keyword">int</span> temp = Math.max(first + nums[i], second);</span><br><span class="line">            first = second;</span><br><span class="line">            second = temp;</span><br><span class="line">        &#125;</span><br><span class="line">        rangeB = second;</span><br><span class="line">        <span class="keyword">return</span> Math.max(rangeA, rangeB);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="87-扰乱字符串">87. 扰乱字符串</h2>
<p><a href="https://leetcode-cn.com/problems/scramble-string/" target="_blank" rel="noopener">扰乱字符串</a></p>
<p>利用递归模拟这个过程，用 for 来模拟所有随机的可能。</p>
<p>超时代码：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isScramble</span><span class="params">(String s1, String s2)</span> </span>&#123;</span><br><span class="line">            <span class="comment">// 相等直接返回true</span></span><br><span class="line">            <span class="keyword">if</span> (s1.equals(s2)) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">// 比较词频，词频不同一定不同</span></span><br><span class="line">            <span class="keyword">if</span> (!check(s1, s2)) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">int</span> length = s1.length();</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt; length; i++) &#123;</span><br><span class="line">                <span class="comment">// s1 = s1[0,i) + s1[i,length)</span></span><br><span class="line">                <span class="comment">// s2 = s2[0,i) + s2[i,length)</span></span><br><span class="line">                <span class="comment">// 1) 保持顺序不变，那么比较 s1[0,i) &amp;&amp; s1[i,length)  和  s2[0,i) &amp;&amp; s2[i,length)</span></span><br><span class="line">                <span class="comment">// 2) 交换子字符串，那么比较 s1[0,i) &amp;&amp; s1[i,length)  和  s2[length-i,length) &amp;&amp; s2[0,length - i)</span></span><br><span class="line">                <span class="keyword">if</span> ((isScramble(s1.substring(<span class="number">0</span>, i), s2.substring(<span class="number">0</span>, i)) &amp;&amp; isScramble(s1.substring(i, length), s2.substring(i, length)))</span><br><span class="line">                || (isScramble(s1.substring(<span class="number">0</span>, i), s2.substring(length - i, length)) &amp;&amp; isScramble(s1.substring(i, length), s2.substring(<span class="number">0</span>, length - i)))) &#123;</span><br><span class="line">                    <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">check</span><span class="params">(String s1, String s2)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (s1.length() != s2.length()) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        Set&lt;Character&gt; set = <span class="keyword">new</span> HashSet&lt;&gt;();</span><br><span class="line">        <span class="keyword">int</span> length = s1.length();</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; length; i++) &#123;</span><br><span class="line">            <span class="keyword">char</span> a = s1.charAt(i);</span><br><span class="line">            <span class="keyword">char</span> b = s2.charAt(i);</span><br><span class="line">            <span class="keyword">if</span> (set.contains(a)) &#123;</span><br><span class="line">                set.remove(a);</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                set.add(a);</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (set.contains(b)) &#123;</span><br><span class="line">                set.remove(b);</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                set.add(b);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> set.isEmpty();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>记忆化搜索：开辟一块内存来存储搜索结果，下次遇到直接返回结果，节约时间。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 记忆化搜索，保存每次 s1 和 s2 的比较结果</span></span><br><span class="line">    Map&lt;String, Map&lt;String, Boolean&gt;&gt; map = <span class="keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isScramble</span><span class="params">(String s1, String s2)</span> </span>&#123;</span><br><span class="line">            <span class="comment">// 相等直接返回true</span></span><br><span class="line">            <span class="keyword">if</span> (s1.equals(s2)) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">// 比较词频，词频不同一定不同</span></span><br><span class="line">            <span class="keyword">if</span> (!check(s1, s2)) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (map.containsKey(s1) &amp;&amp; map.get(s1).containsKey(s2)) &#123;</span><br><span class="line">                <span class="keyword">return</span> map.get(s1).get(s2);</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">int</span> length = s1.length();</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt; length; i++) &#123;</span><br><span class="line">                <span class="comment">// s1 = s1[0,i) + s1[i,length)</span></span><br><span class="line">                <span class="comment">// s2 = s2[0,i) + s2[i,length)</span></span><br><span class="line">                <span class="comment">// 1) 保持顺序不变，那么比较 s1[0,i) &amp;&amp; s1[i,length)  和  s2[0,i) &amp;&amp; s2[i,length)</span></span><br><span class="line">                <span class="comment">// 2) 交换子字符串，那么比较 s1[0,i) &amp;&amp; s1[i,length)  和  s2[length-i,length) &amp;&amp; s2[0,length - i)</span></span><br><span class="line">                <span class="keyword">if</span> ((isScramble(s1.substring(<span class="number">0</span>, i), s2.substring(<span class="number">0</span>, i)) &amp;&amp; isScramble(s1.substring(i, length), s2.substring(i, length)))</span><br><span class="line">                || (isScramble(s1.substring(<span class="number">0</span>, i), s2.substring(length - i, length)) &amp;&amp; isScramble(s1.substring(i, length), s2.substring(<span class="number">0</span>, length - i)))) &#123;</span><br><span class="line">                    map.computeIfAbsent(s1, V -&gt; <span class="keyword">new</span> HashMap&lt;&gt;()).put(s2, <span class="keyword">true</span>);</span><br><span class="line">                    <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            map.computeIfAbsent(s1, V -&gt; <span class="keyword">new</span> HashMap&lt;&gt;()).put(s2, <span class="keyword">false</span>);</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">check</span><span class="params">(String s1, String s2)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (s1.length() != s2.length()) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        Set&lt;Character&gt; set = <span class="keyword">new</span> HashSet&lt;&gt;();</span><br><span class="line">        <span class="keyword">int</span> length = s1.length();</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; length; i++) &#123;</span><br><span class="line">            <span class="keyword">char</span> a = s1.charAt(i);</span><br><span class="line">            <span class="keyword">char</span> b = s2.charAt(i);</span><br><span class="line">            <span class="keyword">if</span> (set.contains(a)) &#123;</span><br><span class="line">                set.remove(a);</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                set.add(a);</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (set.contains(b)) &#123;</span><br><span class="line">                set.remove(b);</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                set.add(b);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> set.isEmpty();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="220-存在重复元素iii">220. 存在重复元素III</h2>
<p><a href="https://leetcode-cn.com/problems/contains-duplicate-iii/" target="_blank" rel="noopener">存在重复元素 III</a></p>
<blockquote>
<p>给你一个整数数组 nums 和两个整数 k 和 t 。请你判断是否存在 两个不同下标 i 和 j，使得 abs(nums[i] - nums[j]) &lt;= t ，同时又满足 abs(i - j) &lt;= k 。</p>
</blockquote>
<p>测试用例数字很大，所以应该考虑用 Long 来避免溢出问题。</p>
<p><strong>方法1：滑动窗口 + TreeSet</strong></p>
<p>滑动窗口来维护区间 <code>[i-t, i+t]</code>。</p>
<p>TreeSet 支持添加和删除指定元素的操作，且内部元素有序，支持条件查找：</p>
<ul>
<li>E ceiling(E e)：查找是否有大于等于 e 的元素</li>
<li>E floor(E e)：查找是否有小于等于 e 的元素</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">containsNearbyAlmostDuplicate</span><span class="params">(<span class="keyword">int</span>[] nums, <span class="keyword">int</span> k, <span class="keyword">int</span> t)</span> </span>&#123;</span><br><span class="line">        TreeSet&lt;Long&gt; set = <span class="keyword">new</span> TreeSet&lt;&gt;();</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; nums.length; i++) &#123;</span><br><span class="line">            <span class="comment">// 集合中是否有元素的值在 [nums[i] - t, nums[i] + t] 之间</span></span><br><span class="line">            <span class="comment">// 集合中是否有满足下界的元素</span></span><br><span class="line">            Long ceiling = set.ceiling((<span class="keyword">long</span>)nums[i] - (<span class="keyword">long</span>)t);</span><br><span class="line">            <span class="comment">// 上界</span></span><br><span class="line">            <span class="keyword">if</span> (ceiling != <span class="keyword">null</span> &amp;&amp; ceiling &lt;= (<span class="keyword">long</span>)nums[i] + (<span class="keyword">long</span>)t) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            set.add((<span class="keyword">long</span>)nums[i]);</span><br><span class="line">            <span class="comment">// 维护滑动窗口</span></span><br><span class="line">            <span class="keyword">if</span> (i &gt;= k) &#123;</span><br><span class="line">                set.remove((<span class="keyword">long</span>)nums[i - k]);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>方法2：桶排序</strong></p>
<p>大概意思是对于数 <code>x</code> 来讲，满足 <code>[x-t, x+t]</code> 的数 y 一定有：<code>(x+1)/(x+1)-1=(y+1)/(y+1)-1</code>。然后分为 <code>t+1</code> 个桶，维护这个桶的数量，每次判断当前的数字落在哪一个桶中。一个桶中有两个数字则直接返回 true，相邻的桶也有可能存在满足的情况。</p>
<h1 id="12-剑指offer">12、剑指Offer</h1>
<h2 id="jz12-数值的整数次方">JZ12 数值的整数次方</h2>
<p><a href="https://www.nowcoder.com/practice/1a834e5e3e1a4b7ba251417554e07c00?tpId=13&amp;tags=&amp;title=&amp;diffculty=0&amp;judgeStatus=0&amp;rp=1&amp;tab=answerKey" target="_blank" rel="noopener">数值的整数次方</a></p>
<blockquote>
<p>给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。</p>
<p>保证base和exponent不同时为0</p>
</blockquote>
<p>快速幂方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">double</span> <span class="title">Power</span><span class="params">(<span class="keyword">double</span> base, <span class="keyword">int</span> exponent)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 快速幂</span></span><br><span class="line">        <span class="keyword">boolean</span> isNegative = <span class="keyword">false</span>;</span><br><span class="line">        <span class="comment">// exponent 转换为正数的原因为：</span></span><br><span class="line">        <span class="comment">// 在 exponent 为奇数时，负数减1，越减越小了</span></span><br><span class="line">        <span class="keyword">if</span> (exponent &lt; <span class="number">0</span>) &#123;</span><br><span class="line">            isNegative = <span class="keyword">true</span>;</span><br><span class="line">            exponent = - exponent;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">double</span> res = getPower(base, exponent);</span><br><span class="line">        <span class="keyword">return</span> isNegative ? <span class="number">1</span> / res : res;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">double</span> <span class="title">getPower</span><span class="params">(<span class="keyword">double</span> base, <span class="keyword">int</span> exponent)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (exponent == <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (exponent % <span class="number">2</span> == <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="keyword">double</span> temp = getPower(base, exponent / <span class="number">2</span>);</span><br><span class="line">            <span class="keyword">return</span> temp * temp;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> getPower(base, exponent - <span class="number">1</span>) * base;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="jz13-调整数组顺序使奇数位于偶数前面">JZ13 调整数组顺序使奇数位于偶数前面</h2>
<p><a href="https://www.nowcoder.com/practice/ef1f53ef31ca408cada5093c8780f44b?tpId=13&amp;tags=&amp;title=&amp;diffculty=0&amp;judgeStatus=0&amp;rp=1&amp;tab=answerKey" target="_blank" rel="noopener">调整数组顺序使奇数位于偶数前面</a></p>
<blockquote>
<p>输入一个整数数组，实现一个函数来调整该数组中数字的顺序，使得所有的奇数位于数组的前半部分，所有的偶数位于数组的后半部分，并保证奇数和奇数，偶数和偶数之间的相对位置不变。</p>
</blockquote>
<p>冒泡</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">int</span>[] reOrderArray (<span class="keyword">int</span>[] array) &#123;</span><br><span class="line">        <span class="keyword">int</span> n = array.length;</span><br><span class="line">        <span class="keyword">boolean</span> changed = <span class="keyword">true</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = n - <span class="number">1</span>; i &gt; <span class="number">0</span> &amp;&amp; changed; i--) &#123;</span><br><span class="line">            changed = <span class="keyword">false</span>;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">0</span>; j &lt; array.length - <span class="number">1</span>; j++) &#123;</span><br><span class="line">                <span class="keyword">if</span> (array[j] % <span class="number">2</span> == <span class="number">0</span> &amp;&amp; array[j + <span class="number">1</span>] % <span class="number">2</span> == <span class="number">1</span>) &#123;</span><br><span class="line">                    changed = <span class="keyword">true</span>;</span><br><span class="line">                    <span class="keyword">int</span> temp = array[j];</span><br><span class="line">                    array[j] = array[j + <span class="number">1</span>];</span><br><span class="line">                    array[j + <span class="number">1</span>] = temp;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> array;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>先取出来偶数，奇数往前挪，再把偶数填进去</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">int</span>[] reOrderArray (<span class="keyword">int</span>[] array) &#123;</span><br><span class="line">        List&lt;Integer&gt; evenNumberList = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">        <span class="keyword">int</span> k = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; array.length; i++) &#123;</span><br><span class="line">            <span class="keyword">if</span> (array[i] % <span class="number">2</span> == <span class="number">0</span>) &#123;</span><br><span class="line">                evenNumberList.add(array[i]);</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                array[k] = array[i];</span><br><span class="line">                k++;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> evenNumber : evenNumberList) &#123;</span><br><span class="line">            array[k++] = evenNumber;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> array;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="jz46-孩子们得游戏圆圈中最后剩下得数">JZ46 孩子们得游戏（圆圈中最后剩下得数）</h2>
<p><a href="https://www.nowcoder.com/practice/f78a359491e64a50bce2d89cff857eb6?tpId=13&amp;tqId=11199&amp;rp=1&amp;ru=%2Fta%2Fcoding-interviews&amp;qru=%2Fta%2Fcoding-interviews%2Fquestion-ranking&amp;tab=answerKey" target="_blank" rel="noopener">孩子们得游戏（圆圈中最后剩下得数）</a></p>
<p><strong>模拟</strong></p>
<p>报数到 <code>m-1</code> 的人就被丢出去，最后得到的就是结果。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.*;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">LastRemaining_Solution</span><span class="params">(<span class="keyword">int</span> n, <span class="keyword">int</span> m)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span>(n == <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> -<span class="number">1</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        List&lt;Integer&gt; list = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; n; i++) &#123;</span><br><span class="line">            list.add(i);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">int</span> index = <span class="number">0</span>, p = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">while</span> (list.size() &gt; <span class="number">1</span>) &#123;</span><br><span class="line">            <span class="keyword">if</span> (p == m - <span class="number">1</span>) &#123;</span><br><span class="line">                list.remove(index);</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                index++;</span><br><span class="line">                index %= list.size();</span><br><span class="line">            &#125;</span><br><span class="line">            p++;</span><br><span class="line">            p %= m;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> list.get(<span class="number">0</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>约瑟夫环</strong></p>
<p>最后一个报数的就是胜利者。</p>
<p>n 个人的情况下，报到 m-1 的人（此人编号为 <code>m % n - 1</code>）退出，剩下的人从 0 开始继续报数，那么可以知道下一个报数的人编号为 <code>m % n</code>，剩下的 n-1 个人组成了一个新的约瑟夫环（以编号为 <code>k = m % n</code> 的人开始）：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">k, k+1, k+2, ..., n-2, n-1, 0, 1, 2, ..., k-2</span><br></pre></td></tr></table></figure>
<p>现在我们把他们的编号做一下转换：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">k, k+1, k+2, ..., n-2, n-1, 0, 1, 2, ..., k-2</span><br><span class="line">0,  1 ,  2 , ..........................., n-2</span><br></pre></td></tr></table></figure>
<p>这时的问题转换为：n-1 个人的情况下，第一个出局的人的编号是 <code>m % (n - 1) - 1</code>，接下来开始报数的人的编号是 <code>k = m % (n - 1)</code> 根据编号转换的关系，此人在 n 个人的情况下，其编号为 `</p>
<h1 id="热题100">热题100</h1>
<h2 id="31下一个排列">31.下一个排列</h2>
<p><a href="https://leetcode-cn.com/problems/next-permutation/" target="_blank" rel="noopener">下一个排列</a></p>
<blockquote>
<p>实现获取 下一个排列 的函数，算法需要将给定数字序列重新排列成字典序中下一个更大的排列。</p>
<p>如果不存在下一个更大的排列，则将数字重新排列成最小的排列（即升序排列）。</p>
<p>必须 原地 修改，只允许使用额外常数空间。</p>
</blockquote>
<p>我们需要将一个左边的「较小数」与一个右边的「较大数」交换，以能够让当前排列变大，从而得到下一个排列。</p>
<p>同时我们要让这个「较小数」尽量靠右，而「较大数」尽可能小。当交换完成后，「较大数」右边的数需要按照升序重新排列。这样可以在保证新排列大于原来排列的情况下，使变大的幅度尽可能小。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">nextPermutation</span><span class="params">(<span class="keyword">int</span>[] nums)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> i = nums.length - <span class="number">2</span>;</span><br><span class="line">        <span class="comment">// 1.找到第一个较小数，满足 nums[i] &lt; nums[i+1]</span></span><br><span class="line">        <span class="keyword">while</span> (i &gt;= <span class="number">0</span> &amp;&amp; !(nums[i] &lt; nums[i + <span class="number">1</span>])) &#123;</span><br><span class="line">            i--;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (i &gt;= <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="comment">// 2.找到靠右的较大数，并交换</span></span><br><span class="line">            <span class="keyword">int</span> j = nums.length - <span class="number">1</span>;</span><br><span class="line">            <span class="keyword">while</span> (j &gt; i &amp;&amp; !(nums[j] &gt; nums[i])) &#123;</span><br><span class="line">                j--;</span><br><span class="line">            &#125;</span><br><span class="line">            swap(nums, i, j);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 此时可以保证区间 [i + 1, nums.length] 一定是降序</span></span><br><span class="line">        <span class="comment">// 3.翻转区间[i, nums.length-1]</span></span><br><span class="line">        <span class="comment">//  a.如果 1. 中没找到合适的较小数，说明已经是最大数（整个数组是降序的），此时直接翻转就是最小数</span></span><br><span class="line">        <span class="comment">//  b.如果 1. 中找到了合适的较小数，为了保证变大的幅度尽可能的小，翻转区间[i+1 , nums.length-1]让它按照升序排列</span></span><br><span class="line">        reverse(nums, i + <span class="number">1</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">reverse</span><span class="params">(<span class="keyword">int</span>[] nums, <span class="keyword">int</span> k)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> l = k, r = nums.length - <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">while</span> (l &lt; r) &#123;</span><br><span class="line">            swap(nums, l++, r--);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">swap</span><span class="params">(<span class="keyword">int</span>[] nums, <span class="keyword">int</span> i, <span class="keyword">int</span> j)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> temp = nums[i];</span><br><span class="line">        nums[i] = nums[j];</span><br><span class="line">        nums[j] = temp;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

                
                <hr>
                <!-- Pager -->
                <ul class="pager">
                    
                        <li class="previous">
                            <a href="/article/算法—两数之和三数之和四数之和/" data-toggle="tooltip" data-placement="top" title="两数之和三数之和四数之和">&larr; 上一篇</a>
                        </li>
                    
                    
                        <li class="next">
                            <a href="/article/JVM/" data-toggle="tooltip" data-placement="top" title="JVM—内存结构、垃圾回收、类加载与字节码技术">下一篇 &rarr;</a>
                        </li>
                    
                </ul>

                <br>

                <!--打赏-->
                
                <!--打赏-->

                <br>
                <!--分享-->
                
                <!--分享-->
                <br>                       
                
                <!-- require APlayer -->
                
            </div>
            
            <!-- Tabe of Content -->
            <!-- Table of Contents -->

  
    <style>
      span.toc-nav-number{
        display: none
      }
    </style>
  
    
      <aside id="sidebar">
        <div id="toc" class="toc-article">
        <strong class="toc-title">目录</strong>
        
          <ol class="toc-nav"><li class="toc-nav-item toc-nav-level-1"><a class="toc-nav-link" href="#1-二叉树专题"><span class="toc-nav-number">1.</span> <span class="toc-nav-text">1&#x3001;&#x4E8C;&#x53C9;&#x6811;&#x4E13;&#x9898;</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#总结"><span class="toc-nav-number">1.1.</span> <span class="toc-nav-text">&#x603B;&#x7ED3;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#模板"><span class="toc-nav-number">1.2.</span> <span class="toc-nav-text">&#x6A21;&#x677F;</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#前序遍历模板递归"><span class="toc-nav-number">1.2.1.</span> <span class="toc-nav-text">&#x524D;&#x5E8F;&#x904D;&#x5386;&#x6A21;&#x677F;&#xFF08;&#x9012;&#x5F52;&#xFF09;</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#前序遍历模板迭代"><span class="toc-nav-number">1.2.2.</span> <span class="toc-nav-text">&#x524D;&#x5E8F;&#x904D;&#x5386;&#x6A21;&#x677F;&#xFF08;&#x8FED;&#x4EE3;&#xFF09;</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#中序遍历模板递归"><span class="toc-nav-number">1.2.3.</span> <span class="toc-nav-text">&#x4E2D;&#x5E8F;&#x904D;&#x5386;&#x6A21;&#x677F;&#xFF08;&#x9012;&#x5F52;&#xFF09;</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#中序遍历模板迭代"><span class="toc-nav-number">1.2.4.</span> <span class="toc-nav-text">&#x4E2D;&#x5E8F;&#x904D;&#x5386;&#x6A21;&#x677F;&#xFF08;&#x8FED;&#x4EE3;&#xFF09;</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#后续遍历模板递归"><span class="toc-nav-number">1.2.5.</span> <span class="toc-nav-text">&#x540E;&#x7EED;&#x904D;&#x5386;&#x6A21;&#x677F;&#xFF08;&#x9012;&#x5F52;&#xFF09;</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#后续遍历模板1迭代"><span class="toc-nav-number">1.2.6.</span> <span class="toc-nav-text">&#x540E;&#x7EED;&#x904D;&#x5386;&#x6A21;&#x677F;1&#xFF08;&#x8FED;&#x4EE3;&#xFF09;</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#后续遍历模板2迭代"><span class="toc-nav-number">1.2.7.</span> <span class="toc-nav-text">&#x540E;&#x7EED;&#x904D;&#x5386;&#x6A21;&#x677F;2&#xFF08;&#x8FED;&#x4EE3;&#xFF09;</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#层次遍历模板-bfs模板"><span class="toc-nav-number">1.2.8.</span> <span class="toc-nav-text">&#x5C42;&#x6B21;&#x904D;&#x5386;&#x6A21;&#x677F; BFS&#x6A21;&#x677F;</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#层次遍历模板-bfs模板-可以确定遍历到哪一层"><span class="toc-nav-number">1.2.9.</span> <span class="toc-nav-text">&#x5C42;&#x6B21;&#x904D;&#x5386;&#x6A21;&#x677F; BFS&#x6A21;&#x677F; &#x53EF;&#x4EE5;&#x786E;&#x5B9A;&#x904D;&#x5386;&#x5230;&#x54EA;&#x4E00;&#x5C42;</span></a></li></ol></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#144-二叉树的前序遍历"><span class="toc-nav-number">1.3.</span> <span class="toc-nav-text">144. &#x4E8C;&#x53C9;&#x6811;&#x7684;&#x524D;&#x5E8F;&#x904D;&#x5386;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#94-二叉树的中序遍历"><span class="toc-nav-number">1.4.</span> <span class="toc-nav-text">94. &#x4E8C;&#x53C9;&#x6811;&#x7684;&#x4E2D;&#x5E8F;&#x904D;&#x5386;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#145-二叉树的后序遍历"><span class="toc-nav-number">1.5.</span> <span class="toc-nav-text">145. &#x4E8C;&#x53C9;&#x6811;&#x7684;&#x540E;&#x5E8F;&#x904D;&#x5386;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#102-二叉树的层序遍历"><span class="toc-nav-number">1.6.</span> <span class="toc-nav-text">102.  &#x4E8C;&#x53C9;&#x6811;&#x7684;&#x5C42;&#x5E8F;&#x904D;&#x5386;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#107-二叉树的层次遍历-ii"><span class="toc-nav-number">1.7.</span> <span class="toc-nav-text">107. &#x4E8C;&#x53C9;&#x6811;&#x7684;&#x5C42;&#x6B21;&#x904D;&#x5386; II</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#103-二叉树的锯齿形层次遍历"><span class="toc-nav-number">1.8.</span> <span class="toc-nav-text">103. &#x4E8C;&#x53C9;&#x6811;&#x7684;&#x952F;&#x9F7F;&#x5F62;&#x5C42;&#x6B21;&#x904D;&#x5386;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#104-二叉树的最大深度"><span class="toc-nav-number">1.9.</span> <span class="toc-nav-text">104. &#x4E8C;&#x53C9;&#x6811;&#x7684;&#x6700;&#x5927;&#x6DF1;&#x5EA6;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#110-平衡二叉树"><span class="toc-nav-number">1.10.</span> <span class="toc-nav-text">110. &#x5E73;&#x8861;&#x4E8C;&#x53C9;&#x6811;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#124-二叉树中的最大路径和"><span class="toc-nav-number">1.11.</span> <span class="toc-nav-text">124. &#x4E8C;&#x53C9;&#x6811;&#x4E2D;&#x7684;&#x6700;&#x5927;&#x8DEF;&#x5F84;&#x548C;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#236-二叉树的最近公共祖先"><span class="toc-nav-number">1.12.</span> <span class="toc-nav-text">236. &#x4E8C;&#x53C9;&#x6811;&#x7684;&#x6700;&#x8FD1;&#x516C;&#x5171;&#x7956;&#x5148;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#98-验证二叉搜索树"><span class="toc-nav-number">1.13.</span> <span class="toc-nav-text">98. &#x9A8C;&#x8BC1;&#x4E8C;&#x53C9;&#x641C;&#x7D22;&#x6811;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#701-二叉搜索树中的插入操作"><span class="toc-nav-number">1.14.</span> <span class="toc-nav-text">701. &#x4E8C;&#x53C9;&#x641C;&#x7D22;&#x6811;&#x4E2D;&#x7684;&#x63D2;&#x5165;&#x64CD;&#x4F5C;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#450-删除二叉搜索树中的节点"><span class="toc-nav-number">1.15.</span> <span class="toc-nav-text">450. &#x5220;&#x9664;&#x4E8C;&#x53C9;&#x641C;&#x7D22;&#x6811;&#x4E2D;&#x7684;&#x8282;&#x70B9;</span></a></li></ol></li><li class="toc-nav-item toc-nav-level-1"><a class="toc-nav-link" href="#2-链表"><span class="toc-nav-number">2.</span> <span class="toc-nav-text">2&#x3001;&#x94FE;&#x8868;</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#83-删除排序链表中的重复元素"><span class="toc-nav-number">2.1.</span> <span class="toc-nav-text">83. &#x5220;&#x9664;&#x6392;&#x5E8F;&#x94FE;&#x8868;&#x4E2D;&#x7684;&#x91CD;&#x590D;&#x5143;&#x7D20;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#82-删除排序链表中的重复元素-ii"><span class="toc-nav-number">2.2.</span> <span class="toc-nav-text">82. &#x5220;&#x9664;&#x6392;&#x5E8F;&#x94FE;&#x8868;&#x4E2D;&#x7684;&#x91CD;&#x590D;&#x5143;&#x7D20; II</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#206-反转链表"><span class="toc-nav-number">2.3.</span> <span class="toc-nav-text">206. &#x53CD;&#x8F6C;&#x94FE;&#x8868;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#92-反转链表-ii"><span class="toc-nav-number">2.4.</span> <span class="toc-nav-text">92. &#x53CD;&#x8F6C;&#x94FE;&#x8868; II</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#21-合并两个有序链表"><span class="toc-nav-number">2.5.</span> <span class="toc-nav-text">21. &#x5408;&#x5E76;&#x4E24;&#x4E2A;&#x6709;&#x5E8F;&#x94FE;&#x8868;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#86-分隔链表"><span class="toc-nav-number">2.6.</span> <span class="toc-nav-text">86. &#x5206;&#x9694;&#x94FE;&#x8868;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#148-排序链表"><span class="toc-nav-number">2.7.</span> <span class="toc-nav-text">148. &#x6392;&#x5E8F;&#x94FE;&#x8868;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#143-重排链表"><span class="toc-nav-number">2.8.</span> <span class="toc-nav-text">143. &#x91CD;&#x6392;&#x94FE;&#x8868;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#141-环形链表"><span class="toc-nav-number">2.9.</span> <span class="toc-nav-text">141. &#x73AF;&#x5F62;&#x94FE;&#x8868;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#142-环形链表-ii"><span class="toc-nav-number">2.10.</span> <span class="toc-nav-text">142. &#x73AF;&#x5F62;&#x94FE;&#x8868; II</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#234-回文链表"><span class="toc-nav-number">2.11.</span> <span class="toc-nav-text">234. &#x56DE;&#x6587;&#x94FE;&#x8868;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#138-复制带随机指针的链表"><span class="toc-nav-number">2.12.</span> <span class="toc-nav-text">138. &#x590D;&#x5236;&#x5E26;&#x968F;&#x673A;&#x6307;&#x9488;&#x7684;&#x94FE;&#x8868;</span></a></li></ol></li><li class="toc-nav-item toc-nav-level-1"><a class="toc-nav-link" href="#3-栈和队列"><span class="toc-nav-number">3.</span> <span class="toc-nav-text">3&#x3001;&#x6808;&#x548C;&#x961F;&#x5217;</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#155-最小栈"><span class="toc-nav-number">3.1.</span> <span class="toc-nav-text">155. &#x6700;&#x5C0F;&#x6808;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#150-逆波兰表达式求值"><span class="toc-nav-number">3.2.</span> <span class="toc-nav-text">150. &#x9006;&#x6CE2;&#x5170;&#x8868;&#x8FBE;&#x5F0F;&#x6C42;&#x503C;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#394-字符串解码"><span class="toc-nav-number">3.3.</span> <span class="toc-nav-text">394. &#x5B57;&#x7B26;&#x4E32;&#x89E3;&#x7801;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#94-二叉树的中序遍历"><span class="toc-nav-number">3.4.</span> <span class="toc-nav-text">94. &#x4E8C;&#x53C9;&#x6811;&#x7684;&#x4E2D;&#x5E8F;&#x904D;&#x5386;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#133-克隆图"><span class="toc-nav-number">3.5.</span> <span class="toc-nav-text">133. &#x514B;&#x9686;&#x56FE;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#200-岛屿数量岛屿类问题通解"><span class="toc-nav-number">3.6.</span> <span class="toc-nav-text">200. &#x5C9B;&#x5C7F;&#x6570;&#x91CF;&#xFF08;&#x5C9B;&#x5C7F;&#x7C7B;&#x95EE;&#x9898;&#x901A;&#x89E3;&#xFF09;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#84-柱状图中最大的矩形单调栈"><span class="toc-nav-number">3.7.</span> <span class="toc-nav-text">84. &#x67F1;&#x72B6;&#x56FE;&#x4E2D;&#x6700;&#x5927;&#x7684;&#x77E9;&#x5F62;&#xFF08;&#x5355;&#x8C03;&#x6808;&#xFF09;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#232-用栈实现队列"><span class="toc-nav-number">3.8.</span> <span class="toc-nav-text">232. &#x7528;&#x6808;&#x5B9E;&#x73B0;&#x961F;&#x5217;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#542-01-矩阵多源bfs问题"><span class="toc-nav-number">3.9.</span> <span class="toc-nav-text">542. 01 &#x77E9;&#x9635;&#xFF08;&#x591A;&#x6E90;BFS&#x95EE;&#x9898;&#xFF09;</span></a></li></ol></li><li class="toc-nav-item toc-nav-level-1"><a class="toc-nav-link" href="#4-二进制"><span class="toc-nav-number">4.</span> <span class="toc-nav-text">4&#x3001;&#x4E8C;&#x8FDB;&#x5236;</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#常见二进制操作"><span class="toc-nav-number">4.1.</span> <span class="toc-nav-text">&#x5E38;&#x89C1;&#x4E8C;&#x8FDB;&#x5236;&#x64CD;&#x4F5C;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#136-只出现一次的数字"><span class="toc-nav-number">4.2.</span> <span class="toc-nav-text">136. &#x53EA;&#x51FA;&#x73B0;&#x4E00;&#x6B21;&#x7684;&#x6570;&#x5B57;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#137-只出现一次的数字-ii"><span class="toc-nav-number">4.3.</span> <span class="toc-nav-text">137. &#x53EA;&#x51FA;&#x73B0;&#x4E00;&#x6B21;&#x7684;&#x6570;&#x5B57; II</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#260-只出现一次的数字-iii"><span class="toc-nav-number">4.4.</span> <span class="toc-nav-text">260. &#x53EA;&#x51FA;&#x73B0;&#x4E00;&#x6B21;&#x7684;&#x6570;&#x5B57; III</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#191-位1的个数"><span class="toc-nav-number">4.5.</span> <span class="toc-nav-text">191. &#x4F4D;1&#x7684;&#x4E2A;&#x6570;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#338-比特位计数"><span class="toc-nav-number">4.6.</span> <span class="toc-nav-text">338. &#x6BD4;&#x7279;&#x4F4D;&#x8BA1;&#x6570;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#190-颠倒二进制位"><span class="toc-nav-number">4.7.</span> <span class="toc-nav-text">190. &#x98A0;&#x5012;&#x4E8C;&#x8FDB;&#x5236;&#x4F4D;</span></a></li></ol></li><li class="toc-nav-item toc-nav-level-1"><a class="toc-nav-link" href="#5-二分搜索"><span class="toc-nav-number">5.</span> <span class="toc-nav-text">5&#x3001;&#x4E8C;&#x5206;&#x641C;&#x7D22;</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#二分搜索模板"><span class="toc-nav-number">5.1.</span> <span class="toc-nav-text">&#x4E8C;&#x5206;&#x641C;&#x7D22;&#x6A21;&#x677F;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#704-二分查找"><span class="toc-nav-number">5.2.</span> <span class="toc-nav-text">704. &#x4E8C;&#x5206;&#x67E5;&#x627E;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#35-搜索插入位置"><span class="toc-nav-number">5.3.</span> <span class="toc-nav-text">35. &#x641C;&#x7D22;&#x63D2;&#x5165;&#x4F4D;&#x7F6E;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#74-搜索二维矩阵"><span class="toc-nav-number">5.4.</span> <span class="toc-nav-text">74. &#x641C;&#x7D22;&#x4E8C;&#x7EF4;&#x77E9;&#x9635;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#278-第一个错误的版本"><span class="toc-nav-number">5.5.</span> <span class="toc-nav-text">278. &#x7B2C;&#x4E00;&#x4E2A;&#x9519;&#x8BEF;&#x7684;&#x7248;&#x672C;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#153-寻找旋转排序数组中的最小值"><span class="toc-nav-number">5.6.</span> <span class="toc-nav-text">153. &#x5BFB;&#x627E;&#x65CB;&#x8F6C;&#x6392;&#x5E8F;&#x6570;&#x7EC4;&#x4E2D;&#x7684;&#x6700;&#x5C0F;&#x503C;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#154-寻找旋转排序数组中的最小值-ii"><span class="toc-nav-number">5.7.</span> <span class="toc-nav-text">154. &#x5BFB;&#x627E;&#x65CB;&#x8F6C;&#x6392;&#x5E8F;&#x6570;&#x7EC4;&#x4E2D;&#x7684;&#x6700;&#x5C0F;&#x503C; II</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#33-搜索旋转排序数组"><span class="toc-nav-number">5.8.</span> <span class="toc-nav-text">33. &#x641C;&#x7D22;&#x65CB;&#x8F6C;&#x6392;&#x5E8F;&#x6570;&#x7EC4;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#81-搜索旋转排序数组-ii"><span class="toc-nav-number">5.9.</span> <span class="toc-nav-text">81. &#x641C;&#x7D22;&#x65CB;&#x8F6C;&#x6392;&#x5E8F;&#x6570;&#x7EC4; II</span></a></li></ol></li><li class="toc-nav-item toc-nav-level-1"><a class="toc-nav-link" href="#6-排序算法"><span class="toc-nav-number">6.</span> <span class="toc-nav-text">6&#x3001;&#x6392;&#x5E8F;&#x7B97;&#x6CD5;</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#归并排序"><span class="toc-nav-number">6.1.</span> <span class="toc-nav-text">&#x5F52;&#x5E76;&#x6392;&#x5E8F;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#堆排序"><span class="toc-nav-number">6.2.</span> <span class="toc-nav-text">&#x5806;&#x6392;&#x5E8F;</span></a></li></ol></li><li class="toc-nav-item toc-nav-level-1"><a class="toc-nav-link" href="#7-动态规划"><span class="toc-nav-number">7.</span> <span class="toc-nav-text">7&#x3001;&#x52A8;&#x6001;&#x89C4;&#x5212;</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#下面是矩阵dp"><span class="toc-nav-number">7.1.</span> <span class="toc-nav-text"><strong>&#x4E0B;&#x9762;&#x662F;&#x77E9;&#x9635;dp</strong></span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#120-三角形最小路径和"><span class="toc-nav-number">7.2.</span> <span class="toc-nav-text">120. &#x4E09;&#x89D2;&#x5F62;&#x6700;&#x5C0F;&#x8DEF;&#x5F84;&#x548C;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#64-最小路径和"><span class="toc-nav-number">7.3.</span> <span class="toc-nav-text">64. &#x6700;&#x5C0F;&#x8DEF;&#x5F84;&#x548C;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#62-不同路径"><span class="toc-nav-number">7.4.</span> <span class="toc-nav-text">62. &#x4E0D;&#x540C;&#x8DEF;&#x5F84;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#63-不同路径-ii滚动数组优化空间复杂度"><span class="toc-nav-number">7.5.</span> <span class="toc-nav-text">63. &#x4E0D;&#x540C;&#x8DEF;&#x5F84; II&#x3010;&#x6EDA;&#x52A8;&#x6570;&#x7EC4;&#x4F18;&#x5316;&#x7A7A;&#x95F4;&#x590D;&#x6742;&#x5EA6;&#x3011;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#下面是序列dp"><span class="toc-nav-number">7.6.</span> <span class="toc-nav-text">&#x4E0B;&#x9762;&#x662F;&#x5E8F;&#x5217;dp</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#70-爬楼梯"><span class="toc-nav-number">7.7.</span> <span class="toc-nav-text">70. &#x722C;&#x697C;&#x68AF;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#55-跳跃游戏"><span class="toc-nav-number">7.8.</span> <span class="toc-nav-text">55. &#x8DF3;&#x8DC3;&#x6E38;&#x620F;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#45-跳跃游戏-ii"><span class="toc-nav-number">7.9.</span> <span class="toc-nav-text">45. &#x8DF3;&#x8DC3;&#x6E38;&#x620F; II</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#132-分割回文串-ii"><span class="toc-nav-number">7.10.</span> <span class="toc-nav-text">132. &#x5206;&#x5272;&#x56DE;&#x6587;&#x4E32; II</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#300-最长递增子序列"><span class="toc-nav-number">7.11.</span> <span class="toc-nav-text">300. &#x6700;&#x957F;&#x9012;&#x589E;&#x5B50;&#x5E8F;&#x5217;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#139-单词拆分"><span class="toc-nav-number">7.12.</span> <span class="toc-nav-text">139. &#x5355;&#x8BCD;&#x62C6;&#x5206;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#下面时双序列dp"><span class="toc-nav-number">7.13.</span> <span class="toc-nav-text">&#x4E0B;&#x9762;&#x65F6;&#x53CC;&#x5E8F;&#x5217;DP</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#1143-最长公共子序列"><span class="toc-nav-number">7.14.</span> <span class="toc-nav-text">1143. &#x6700;&#x957F;&#x516C;&#x5171;&#x5B50;&#x5E8F;&#x5217;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#72-编辑距离"><span class="toc-nav-number">7.15.</span> <span class="toc-nav-text">72. &#x7F16;&#x8F91;&#x8DDD;&#x79BB;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#背包和零钱兑换问题"><span class="toc-nav-number">7.16.</span> <span class="toc-nav-text">&#x80CC;&#x5305;&#x548C;&#x96F6;&#x94B1;&#x5151;&#x6362;&#x95EE;&#x9898;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#322-零钱兑换"><span class="toc-nav-number">7.17.</span> <span class="toc-nav-text">322. &#x96F6;&#x94B1;&#x5151;&#x6362;</span></a></li></ol></li><li class="toc-nav-item toc-nav-level-1"><a class="toc-nav-link" href="#8-递归"><span class="toc-nav-number">8.</span> <span class="toc-nav-text">8&#x3001;&#x9012;&#x5F52;</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#24-两两交换链表中的节点"><span class="toc-nav-number">8.1.</span> <span class="toc-nav-text">24. &#x4E24;&#x4E24;&#x4EA4;&#x6362;&#x94FE;&#x8868;&#x4E2D;&#x7684;&#x8282;&#x70B9;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#95-不同的二叉搜索树-ii"><span class="toc-nav-number">8.2.</span> <span class="toc-nav-text">95. &#x4E0D;&#x540C;&#x7684;&#x4E8C;&#x53C9;&#x641C;&#x7D22;&#x6811; II</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#509-斐波那契数"><span class="toc-nav-number">8.3.</span> <span class="toc-nav-text">509. &#x6590;&#x6CE2;&#x90A3;&#x5951;&#x6570;</span></a></li></ol></li><li class="toc-nav-item toc-nav-level-1"><a class="toc-nav-link" href="#9-滑动窗口"><span class="toc-nav-number">9.</span> <span class="toc-nav-text">9&#x3001;&#x6ED1;&#x52A8;&#x7A97;&#x53E3;</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#滑动窗口模板"><span class="toc-nav-number">9.1.</span> <span class="toc-nav-text">&#x6ED1;&#x52A8;&#x7A97;&#x53E3;&#x6A21;&#x677F;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#76-最小覆盖子串"><span class="toc-nav-number">9.2.</span> <span class="toc-nav-text">76. &#x6700;&#x5C0F;&#x8986;&#x76D6;&#x5B50;&#x4E32;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#567-字符串的排列"><span class="toc-nav-number">9.3.</span> <span class="toc-nav-text">567. &#x5B57;&#x7B26;&#x4E32;&#x7684;&#x6392;&#x5217;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#483-找到字符串中所有字母异位词"><span class="toc-nav-number">9.4.</span> <span class="toc-nav-text">483. &#x627E;&#x5230;&#x5B57;&#x7B26;&#x4E32;&#x4E2D;&#x6240;&#x6709;&#x5B57;&#x6BCD;&#x5F02;&#x4F4D;&#x8BCD;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#3-无重复字符的最长子串"><span class="toc-nav-number">9.5.</span> <span class="toc-nav-text">3&#x3001;&#x65E0;&#x91CD;&#x590D;&#x5B57;&#x7B26;&#x7684;&#x6700;&#x957F;&#x5B50;&#x4E32;</span></a></li></ol></li><li class="toc-nav-item toc-nav-level-1"><a class="toc-nav-link" href="#10-回溯法"><span class="toc-nav-number">10.</span> <span class="toc-nav-text">10&#x3001;&#x56DE;&#x6EAF;&#x6CD5;</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#回溯法模板"><span class="toc-nav-number">10.1.</span> <span class="toc-nav-text">&#x56DE;&#x6EAF;&#x6CD5;&#x6A21;&#x677F;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#78-子集"><span class="toc-nav-number">10.2.</span> <span class="toc-nav-text">78.  &#x5B50;&#x96C6;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#90-子集-ii"><span class="toc-nav-number">10.3.</span> <span class="toc-nav-text">90. &#x5B50;&#x96C6; II</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#46-全排列"><span class="toc-nav-number">10.4.</span> <span class="toc-nav-text">46. &#x5168;&#x6392;&#x5217;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#47-全排列-ii"><span class="toc-nav-number">10.5.</span> <span class="toc-nav-text">47. &#x5168;&#x6392;&#x5217; II</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#39-组合总数"><span class="toc-nav-number">10.6.</span> <span class="toc-nav-text">39. &#x7EC4;&#x5408;&#x603B;&#x6570;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#17-电话号码的字母组合"><span class="toc-nav-number">10.7.</span> <span class="toc-nav-text">17. &#x7535;&#x8BDD;&#x53F7;&#x7801;&#x7684;&#x5B57;&#x6BCD;&#x7EC4;&#x5408;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#131-分割回文串"><span class="toc-nav-number">10.8.</span> <span class="toc-nav-text">131. &#x5206;&#x5272;&#x56DE;&#x6587;&#x4E32;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#93-复原ip地址"><span class="toc-nav-number">10.9.</span> <span class="toc-nav-text">93. &#x590D;&#x539F;IP&#x5730;&#x5740;</span></a></li></ol></li><li class="toc-nav-item toc-nav-level-1"><a class="toc-nav-link" href="#11-初级算法"><span class="toc-nav-number">11.</span> <span class="toc-nav-text">11&#x3001;&#x521D;&#x7EA7;&#x7B97;&#x6CD5;</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#1-数组"><span class="toc-nav-number">11.1.</span> <span class="toc-nav-text">1&#x3001;&#x6570;&#x7EC4;</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#26-删除排序数组中的重复项"><span class="toc-nav-number">11.1.1.</span> <span class="toc-nav-text">26. &#x5220;&#x9664;&#x6392;&#x5E8F;&#x6570;&#x7EC4;&#x4E2D;&#x7684;&#x91CD;&#x590D;&#x9879;</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#122-买卖股票的最佳时机-ii"><span class="toc-nav-number">11.1.2.</span> <span class="toc-nav-text">122. &#x4E70;&#x5356;&#x80A1;&#x7968;&#x7684;&#x6700;&#x4F73;&#x65F6;&#x673A; II</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#189-旋转数组"><span class="toc-nav-number">11.1.3.</span> <span class="toc-nav-text">189. &#x65CB;&#x8F6C;&#x6570;&#x7EC4;</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#217-存在重复元素"><span class="toc-nav-number">11.1.4.</span> <span class="toc-nav-text">217. &#x5B58;&#x5728;&#x91CD;&#x590D;&#x5143;&#x7D20;</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#350-两个数组的交集-ii"><span class="toc-nav-number">11.1.5.</span> <span class="toc-nav-text">350. &#x4E24;&#x4E2A;&#x6570;&#x7EC4;&#x7684;&#x4EA4;&#x96C6; II</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#283-移动零"><span class="toc-nav-number">11.1.6.</span> <span class="toc-nav-text">283. &#x79FB;&#x52A8;&#x96F6;</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#1-两数之和"><span class="toc-nav-number">11.1.7.</span> <span class="toc-nav-text">1. &#x4E24;&#x6570;&#x4E4B;&#x548C;</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#36-有效的数独"><span class="toc-nav-number">11.1.8.</span> <span class="toc-nav-text">36. &#x6709;&#x6548;&#x7684;&#x6570;&#x72EC;</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#48-旋转图像"><span class="toc-nav-number">11.1.9.</span> <span class="toc-nav-text">48. &#x65CB;&#x8F6C;&#x56FE;&#x50CF;</span></a></li></ol></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#2-字符串"><span class="toc-nav-number">11.2.</span> <span class="toc-nav-text">2&#x3001;&#x5B57;&#x7B26;&#x4E32;</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#387字符串中的第一个唯一字符"><span class="toc-nav-number">11.2.1.</span> <span class="toc-nav-text">387.&#x5B57;&#x7B26;&#x4E32;&#x4E2D;&#x7684;&#x7B2C;&#x4E00;&#x4E2A;&#x552F;&#x4E00;&#x5B57;&#x7B26;</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#242-有效的字母异位词"><span class="toc-nav-number">11.2.2.</span> <span class="toc-nav-text">242. &#x6709;&#x6548;&#x7684;&#x5B57;&#x6BCD;&#x5F02;&#x4F4D;&#x8BCD;</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#125-验证回文串"><span class="toc-nav-number">11.2.3.</span> <span class="toc-nav-text">125. &#x9A8C;&#x8BC1;&#x56DE;&#x6587;&#x4E32;</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#38-外观数列"><span class="toc-nav-number">11.2.4.</span> <span class="toc-nav-text">38. &#x5916;&#x89C2;&#x6570;&#x5217;</span></a></li></ol></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#3-链表"><span class="toc-nav-number">11.3.</span> <span class="toc-nav-text">3&#x3001;&#x94FE;&#x8868;</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#237-删除链表中的节点"><span class="toc-nav-number">11.3.0.1.</span> <span class="toc-nav-text">237. &#x5220;&#x9664;&#x94FE;&#x8868;&#x4E2D;&#x7684;&#x8282;&#x70B9;</span></a></li></ol></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#19-删除链表的倒数第-n-个节点"><span class="toc-nav-number">11.3.1.</span> <span class="toc-nav-text">19. &#x5220;&#x9664;&#x94FE;&#x8868;&#x7684;&#x5012;&#x6570;&#x7B2C; N &#x4E2A;&#x8282;&#x70B9;</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#234-回文链表"><span class="toc-nav-number">11.3.2.</span> <span class="toc-nav-text">234. &#x56DE;&#x6587;&#x94FE;&#x8868;</span></a></li></ol></li></ol></li><li class="toc-nav-item toc-nav-level-1"><a class="toc-nav-link" href="#无序刷题"><span class="toc-nav-number">12.</span> <span class="toc-nav-text">&#x65E0;&#x5E8F;&#x5237;&#x9898;</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#3-无重复字符的最长子串"><span class="toc-nav-number">12.1.</span> <span class="toc-nav-text">3&#x3001;&#x65E0;&#x91CD;&#x590D;&#x5B57;&#x7B26;&#x7684;&#x6700;&#x957F;&#x5B50;&#x4E32;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#4-寻找两个正序数组的中位数"><span class="toc-nav-number">12.2.</span> <span class="toc-nav-text">4&#x3001;&#x5BFB;&#x627E;&#x4E24;&#x4E2A;&#x6B63;&#x5E8F;&#x6570;&#x7EC4;&#x7684;&#x4E2D;&#x4F4D;&#x6570;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#7-整数反转"><span class="toc-nav-number">12.3.</span> <span class="toc-nav-text">7&#x3001; &#x6574;&#x6570;&#x53CD;&#x8F6C;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#10-正则表达式匹配"><span class="toc-nav-number">12.4.</span> <span class="toc-nav-text">10. &#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;&#x5339;&#x914D;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#13-罗马数字转整数"><span class="toc-nav-number">12.5.</span> <span class="toc-nav-text">13. &#x7F57;&#x9A6C;&#x6570;&#x5B57;&#x8F6C;&#x6574;&#x6570;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#14-最长公共前缀"><span class="toc-nav-number">12.6.</span> <span class="toc-nav-text">14. &#x6700;&#x957F;&#x516C;&#x5171;&#x524D;&#x7F00;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#66-加一"><span class="toc-nav-number">12.7.</span> <span class="toc-nav-text">66. &#x52A0;&#x4E00;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#334-反转字符串"><span class="toc-nav-number">12.8.</span> <span class="toc-nav-text">334. &#x53CD;&#x8F6C;&#x5B57;&#x7B26;&#x4E32;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#213-打家劫舍ii"><span class="toc-nav-number">12.9.</span> <span class="toc-nav-text">213. &#x6253;&#x5BB6;&#x52AB;&#x820D;II</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#87-扰乱字符串"><span class="toc-nav-number">12.10.</span> <span class="toc-nav-text">87. &#x6270;&#x4E71;&#x5B57;&#x7B26;&#x4E32;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#220-存在重复元素iii"><span class="toc-nav-number">12.11.</span> <span class="toc-nav-text">220. &#x5B58;&#x5728;&#x91CD;&#x590D;&#x5143;&#x7D20;III</span></a></li></ol></li><li class="toc-nav-item toc-nav-level-1"><a class="toc-nav-link" href="#12-剑指offer"><span class="toc-nav-number">13.</span> <span class="toc-nav-text">12&#x3001;&#x5251;&#x6307;Offer</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#jz12-数值的整数次方"><span class="toc-nav-number">13.1.</span> <span class="toc-nav-text">JZ12 &#x6570;&#x503C;&#x7684;&#x6574;&#x6570;&#x6B21;&#x65B9;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#jz13-调整数组顺序使奇数位于偶数前面"><span class="toc-nav-number">13.2.</span> <span class="toc-nav-text">JZ13 &#x8C03;&#x6574;&#x6570;&#x7EC4;&#x987A;&#x5E8F;&#x4F7F;&#x5947;&#x6570;&#x4F4D;&#x4E8E;&#x5076;&#x6570;&#x524D;&#x9762;</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#jz46-孩子们得游戏圆圈中最后剩下得数"><span class="toc-nav-number">13.3.</span> <span class="toc-nav-text">JZ46 &#x5B69;&#x5B50;&#x4EEC;&#x5F97;&#x6E38;&#x620F;&#xFF08;&#x5706;&#x5708;&#x4E2D;&#x6700;&#x540E;&#x5269;&#x4E0B;&#x5F97;&#x6570;&#xFF09;</span></a></li></ol></li><li class="toc-nav-item toc-nav-level-1"><a class="toc-nav-link" href="#热题100"><span class="toc-nav-number">14.</span> <span class="toc-nav-text">&#x70ED;&#x9898;100</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#31下一个排列"><span class="toc-nav-number">14.1.</span> <span class="toc-nav-text">31.&#x4E0B;&#x4E00;&#x4E2A;&#x6392;&#x5217;</span></a></li></ol></li></ol>
        
        </div>
      </aside>
    

                
            <!-- Sidebar Container -->
            <div class="
                col-lg-8 col-lg-offset-2
                col-md-10 col-md-offset-1
                sidebar-container">

                <!-- Featured Tags -->
                
                <section>
                    <!-- no hr -->
                    <h5><a href="/tags/">标签</a></h5>
                    <div class="tags">
                       
                          <a class="tag" href="/tags/#algorithm" title="algorithm">algorithm</a>
                        
                    </div>
                </section>
                

                <!-- Friends Blog -->
				<!--
                
                <hr>
                <h5>朋友们</h5>
                <ul class="list-inline">

                    
                        <li><a href="https://tyzhang.top/" target="_blank">ztygalaxy</a></li>
                    
                        <li><a href="http://www.yctang.club/" target="_blank">yctang</a></li>
                    
                        <li><a href="https://dolnw.github.io" target="_blank">JCWang</a></li>
                    
                </ul>
                
				-->
            </div>
        </div>
    </div>
</article>


<!-- async load function -->
<script>
    function async(u, c) {
      var d = document, t = 'script',
          o = d.createElement(t),
          s = d.getElementsByTagName(t)[0];
      o.src = u;
      if (c) { o.addEventListener('load', function (e) { c(null, e); }, false); }
      s.parentNode.insertBefore(o, s);
    }
</script>
<!-- anchor-js, Doc:http://bryanbraun.github.io/anchorjs/ -->
<script>
    async("https://cdn.bootcss.com/anchor-js/1.1.1/anchor.min.js",function(){
        anchors.options = {
          visible: 'hover',
          placement: 'left',
          icon: ''
        };
        anchors.add().remove('.intro-header h1').remove('.subheading').remove('.sidebar-container h5');
    })
</script>
<style>
    /* place left on bigger screen */
    @media all and (min-width: 800px) {
        .anchorjs-link{
            position: absolute;
            left: -0.75em;
            font-size: 1.1em;
            margin-top : -0.1em;
        }
    }
</style>


<!-- chrome Firefox 中文锚点定位失效-->
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
<!-- smooth scroll behavior polyfill  -->
<script type="text/javascript" src="/js/smoothscroll.js"></script>
<script>
        $('#toc').on('click','a',function(a){
            // var isChrome = window.navigator.userAgent.indexOf("Chrome") !== -1;
            // console.log(window.navigator.userAgent,isChrome)
                // if(isChrome) {
                    // console.log(a.currentTarget.outerHTML);
                    // console.log($(a.currentTarget).attr("href"));
                    //跳转到指定锚点
                    // document.getElementById(a.target.innerText.toLowerCase()).scrollIntoView(true);
                    document.getElementById($(a.currentTarget).attr("href").replace("#","")).scrollIntoView({behavior: 'smooth' });
                // }
        })  
</script>


    <!-- Footer -->
    <!-- Footer -->
<footer>
    <div class="container">
        <div class="row">
            <div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
                <ul class="list-inline text-center">
                
                
                
				
                

                

                
                    <li>
                        <a target="_blank"  href="https://github.com/songzblink">
                            <span class="fa-stack fa-lg">
                                <i class="fa fa-circle fa-stack-2x"></i>
                                <i class="fa fa-github fa-stack-1x fa-inverse"></i>
                            </span>
                        </a>
                    </li>
                

                

                </ul>
                <p class="copyright text-muted">
                    Copyright &copy; 宋正兵 2021 
                    <br>
                    Theme by <a href="http://www.huweihuang.com">Huwei Huang</a>
                    re-Ported by <a href="https://github.com/ztygalaxy">ztygalaxy</a>
					
                </p>
            </div>
        </div>
    </div>
</footer>

<!-- jQuery -->
<script src="/js/jquery.min.js"></script>

<!-- Bootstrap Core JavaScript -->
<script src="/js/bootstrap.min.js"></script>

<!-- Custom Theme JavaScript -->
<script src="/js/hux-blog.min.js"></script>


<!-- async load function -->
<script>
    function async(u, c) {
      var d = document, t = 'script',
          o = d.createElement(t),
          s = d.getElementsByTagName(t)[0];
      o.src = u;
      if (c) { o.addEventListener('load', function (e) { c(null, e); }, false); }
      s.parentNode.insertBefore(o, s);
    }
</script>

<!-- 
     Because of the native support for backtick-style fenced code blocks 
     right within the Markdown is landed in Github Pages, 
     From V1.6, There is no need for Highlight.js, 
     so Huxblog drops it officially.

     - https://github.com/blog/2100-github-pages-now-faster-and-simpler-with-jekyll-3-0  
     - https://help.github.com/articles/creating-and-highlighting-code-blocks/    
-->
<!--
    <script>
        async("http://cdn.bootcss.com/highlight.js/8.6/highlight.min.js", function(){
            hljs.initHighlightingOnLoad();
        })
    </script>
    <link href="http://cdn.bootcss.com/highlight.js/8.6/styles/github.min.css" rel="stylesheet">
-->


<!-- jquery.tagcloud.js -->
<script>
    // only load tagcloud.js in tag.html
    if($('#tag_cloud').length !== 0){
        async("zbsong.top/js/jquery.tagcloud.js",function(){
            $.fn.tagcloud.defaults = {
                //size: {start: 1, end: 1, unit: 'em'},
                color: {start: '#bbbbee', end: '#0085a1'},
            };
            $('#tag_cloud a').tagcloud();
        })
    }
</script>

<!--fastClick.js -->
<script>
    async("https://cdn.bootcss.com/fastclick/1.0.6/fastclick.min.js", function(){
        var $nav = document.querySelector("nav");
        if($nav) FastClick.attach($nav);
    })
</script>


<!-- Google Analytics -->




<!-- Baidu Tongji -->






	<a id="rocket" href="#top" class=""></a>
	<script type="text/javascript" src="/js/totop.js?v=1.0.0" async=""></script>
    <script type="text/javascript" src="/js/toc.js?v=1.0.0" async=""></script>
<!-- Image to hack wechat -->
<img src="zbsong.top/img/icon_wechat.png" width="0" height="0" />
<!-- Migrate from head to bottom, no longer block render and still work -->

<script type="text/x-mathjax-config">
    MathJax.Hub.Config({
        tex2jax: {
            inlineMath: [ ["$","$"], ["\\(","\\)"] ],
            skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code'],
            processEscapes: true
        }
    });
    MathJax.Hub.Queue(function() {
        var all = MathJax.Hub.getAllJax();
        for (var i = 0; i < all.length; ++i)
            all[i].SourceElement().parentNode.className += ' has-jax';
    });
</script>
<!--
<script src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_CHTML"></script>
</body>

</html>
